【问题标题】:MustHaveHappened Assert always fails for an async method run on a separate thread (Task.Run)对于在单独的线程 (Task.Run) 上运行的异步方法,MustHaveHappened Assert 总是失败
【发布时间】:2017-04-21 23:00:41
【问题描述】:

我有一个方法:

public class MyClass
{
    public ILogger _logger;

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

还有一个测试用例:

[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 总是说失败

以下调用的断言失败:
MyClass.TestLogMethod()
预计至少会找到一次,但没有调用假对象。

很明显_logger.Log()被调用了,但是为什么这里总是断言失败?

【问题讨论】:

  • 你能先解释一下为什么你有一个 async void 方法等待一个新任务,它等待另一个任务吗?
  • 在我关于async best practices 的文章中,我提到了避免使用async void 方法的几个原因;其中之一是“Async void 方法很难测试。”

标签: c# multithreading nunit fakeiteasy


【解决方案1】:

您不是在等待TestLogMethod 的完成,因此您是在期望发生之前验证它。 Task 将被安排在线程池上,然后该方法将立即返回。这就是为什么你应该avoid async void方法。

更改方法以返回Task,这样您就有了await 的内容。您还可以在此处删除大部分 asyncawait 对,因为它们是多余的:

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

然后await 在你的测试中:

await testClass.TestLogMethod("Test Message");

当验证发生时,对ILogger.Log的调用就会发生。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-08
    • 2022-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-05
    相关资源
    最近更新 更多