1

I have a method:

public class MyClass
{
    public ILogger _logger;

    public async void TestLogMethod(string msg)
    {
        await Task.Run(async ()=> await _logger.Log(msg));
    }
}

And a testcase:

[Test]
public async Task TestLogMethod_LogMessage_Test()
{
    var fakeLogger = A.Fake<ILogger>();
    var testClass = new MyClass();
    testClass._logger = fakeLogger;

    testClass.TestLogMethod("Test Message");

    A.CallTo(() => fakeLogger.Log(A<string>._)).MustHaveHappened();
}

MustHaveHappened Assert always fails saying

Assertion failed for the following call:
MyClass.TestLogMethod<System.Object>(<Ignored>)
Expected to find it at least once but no calls were made to the fake object.

It is clear that _logger.Log() is called, but why is Asserting always failing here ?

Tany
  • 1,252
  • 14
  • 30
  • 1
    Can you start by explaining why you have an `async void` method which awaits for a new task, which awaits for another task? – Federico Dipuma Apr 21 '17 at 14:51
  • Should also look into [Explicit Dependencies Principle](http://deviq.com/explicit-dependencies-principle/) – Nkosi Apr 21 '17 at 15:00
  • 2
    In my article on [async best practices](https://msdn.microsoft.com/en-us/magazine/jj991977.aspx), I mention several reasons to avoid `async void` methods; one of them is "Async void methods are difficult to test." – Stephen Cleary Apr 21 '17 at 15:17

1 Answers1

5

You're not awaiting the completion of TestLogMethod, so you're verifying the expectation before it's happened. The Task will be scheduled on the thread pool and the method will then immediately return. This is why you should avoid async void methods.

Change the method to return a Task so you have something to await. You can also remove most of the async and await pairs here as they're redundant:

public Task TestLogMethod(string msg)
{
    return Task.Run(() => _logger.Log(msg));
}

And then await that in your test:

await testClass.TestLogMethod("Test Message");

And then by the time the verification happens the call to ILogger.Log will have happened.

Charles Mager
  • 25,735
  • 2
  • 35
  • 45