当我运行以下代码时:
[Test]
public async Task Can_Test_Update()
{
var response = await _controller.UpdateAsync(Guid.NewGuid());
response.Valid.Should().BeTrue();
_commands.Received().UpdateAsync(
Arg.Is<Something>(
l => l.Status == Status.Updated));
}
如果我在“
await
”之前添加“_commands.Received().UpdateAsync
”,则会引发空引用异常。我怎样才能阻止这种情况发生,还是await
没有必要?
我在这里找到了答案。
Received.InOrder(async () =>
{
await _Commands.UpdateAsync(Arg.Is<Lobby>(l => l.Status == Status.Updated));
});
_commands.UpdateAsync(Status.Updated))
返回的任务。另一方面,
.Received()
调用正在验证是否调用了异步方法,这是完全同步的,因此不需要等待。要记住的关键是异步方法返回
Task
。调用异步方法并返回任务是完全同步的,然后您可以等待
Task
来了解任务所代表的异步操作何时完成。
这个答案,从 NSubstitute 版本 1.8.3 开始,您可以使用 await
,它将按预期工作,而不是抛出 NullReferenceException。我刚刚尝试过,因为我在版本 1.5.0 上并得到了 NullReferenceException 正如你所描述的,但现在我在最新版本(1.10.0)上,它运行良好。
await
Received
方法:
[Test]
public async Task Can_Test_Update()
{
var response = await _controller.UpdateAsync(Guid.NewGuid());
response.Valid.Should().BeTrue();
await _commands.Received().UpdateAsync(
Arg.Is<Something>(
l => l.Status == Status.Updated));
}
Jake Ginnivan 答案正确指出,对于已接收等待不是必需的,但编译器不理解它并显示
警告 CS4014:由于未等待此调用,因此执行 当前方法在调用完成之前继续。考虑 将“await”运算符应用于调用结果。最简单的解决方法是抑制警告
#pragma warning disable 4014 //for .Received await is not required, so suppress warning “Consider applying the 'await' operator”
_publisher.Received(totalNumber).MyMethod(Arg.Any<ParamType>());
#pragma warning restore 4014
当我在“_commands.Received().UpdateAsync”之前添加“await”时, 出现错误空引用那是因为当您不这样做时
await
,方法 (
Can_Test_Update
) 可能会在实际检查您传递给该方法的 null 值之前结束,这意味着测试结束。你有一个竞争条件。当您在
await
上点击
UpdateAsync
时,该方法实际上异步等待操作完成,并且
UpdateAsync
有机会访问您传递给它的 null。要解决您的错误,只需在
UpdateAsync
内放置一个断点,然后查看哪个值作为 null 传递给该方法。我怀疑
Arg.Is<Something>
是你的问题。
示例:
receivedObject.Stub(s => s.Update(...)).Return(Task.FromResult(0));
编辑
问题出在这一行:
var mockService = Substitute.For<ICalculationServiceAsync>();
或者更准确地说,当你调用它的方法时:
await _service.Calculate();
您创建了一个模拟服务,但没有存根该方法。我不确定如何在 Nunit 中执行此操作(我们主要使用 Rhino,我需要检查),但您需要存根计算方法以返回空任务 (Task.FromResult(0))。默认情况下,存根方法返回默认返回类型,并且 default(Task) 为 null。
关于