3

I am trying to unit test some async code. I was previously using NUnit but would like to switch to Xunit but I can't get some tests working. Here is some example code for some working NUnit tests that I simplified for the sake of asking this question:

[TestFixture]
public class Tests
{
    [Test]
    public async Task UsingAsyncTask()
    {
        // Arrange
        PubSubEvent<object> pubSubEvent = Mock.Create<PubSubEvent<object>>();

        // Act
        await Task.Run(() => { pubSubEvent.Publish(new object()); });

        // Assert
        Mock.Assert(() => pubSubEvent.Publish(null), Args.Ignore(), Occurs.Once());
    }
}

Add the following NuGet packages.config:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="JustMock" version="2015.1.224.3" targetFramework="net45" />
  <package id="Nito.AsyncEx" version="3.0.0" targetFramework="net45" />
  <package id="NUnit" version="2.6.4" targetFramework="net45" />
  <package id="NUnitTestAdapter" version="2.0.0" targetFramework="net45" />
  <package id="Prism.PubSubEvents" version="1.1.2" targetFramework="net45" />
</packages>

All of these unit tests pass without a problem. So I try the same thing in Xunit:

public class Tests
{
    [Fact]
    public async Task UsingAsyncTask()
    {
        // Arrange
        PubSubEvent<object> pubSubEvent = Mock.Create<PubSubEvent<object>>();

        // Act
        await Task.Run(() => { pubSubEvent.Publish(new object()); });

        // Assert
        Mock.Assert(() => pubSubEvent.Publish(null), Args.Ignore(), Occurs.Once());
    }
}

Add the following NuGet packages.config:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="JustMock" version="2015.1.224.3" targetFramework="net45" />
  <package id="Nito.AsyncEx" version="3.0.0" targetFramework="net45" />
  <package id="Prism.PubSubEvents" version="1.1.2" targetFramework="net45" />
  <package id="xunit" version="2.0.0" targetFramework="net45" />
  <package id="xunit.abstractions" version="2.0.0" targetFramework="net45" />
  <package id="xunit.assert" version="2.0.0" targetFramework="net45" />
  <package id="xunit.core" version="2.0.0" targetFramework="net45" />
  <package id="xunit.extensibility.core" version="2.0.0" targetFramework="net45" />
  <package id="xunit.runner.visualstudio" version="2.0.0" targetFramework="net45" />
</packages>

The test fails in Xunit indicating that it is expecting 1 call but has received 0 calls. If I remove the task and run everything synchronously the test passes.

taylorjonl
  • 869
  • 9
  • 15
  • What about that code is async? You're using `Task.Run` to emulate async operations. why add the complexity? (Or is this your way of distilling it down for SO?) – Brad Christie May 14 '15 at 01:47
  • Correct, the actual code is far more complex, just stripped it down so it wasn't too big. – taylorjonl May 14 '15 at 01:50
  • I still feel like if there's no `PublishAsync` natively, then you're wrapping these calls for no reason. Maybe I'm just tired, or paying too much attention to the little details, but looks like you're running async for the sake of doing so. – Brad Christie May 14 '15 at 01:52
  • For this test I am doing it for the sake of the example, in the real application it spins up a Task that does some work, if specific conditions arise while it does this work it should publish an event through the PubSubEvent<> class which is part of Prism.PubSubEvents. – taylorjonl May 14 '15 at 01:57
  • We can't do anything with code that doesn't accurately portray your actual problem. Change method names and leave out stuff that isn't relevant, but don't change something that important. And specify the error messages. – Jeroen Vannevel May 14 '15 at 02:18
  • 2
    For what it's worth, I see the same behavior switching between NUnit and Xunit using JustMock, but if I switch the mocking framework to Moq the test passes in both testing frameworks. – Preston Guillot May 14 '15 at 02:37
  • The code 100% portrays the problem, the code I have removed in no way affects the outcome. Me pasting 200 more lines of code with munged method names in no way will improve the situation because the provided code 100% reproduces the issue. – taylorjonl May 14 '15 at 05:49
  • XUnit provides a `SynchronizationContext` for its test methods. Maybe JustMock is reacting to this? – Stephen Cleary May 14 '15 at 11:54
  • I might be missing something here but why do you need your unit test to be asynchronous? Could you not just do the equivalent of `Task.Run().Wait()` and remove the async and await keywords? – Lars N Jun 25 '15 at 11:58

0 Answers0