我如何告诉Moq返回任务?

Wal*_*mar 291 c# unit-testing moq task-parallel-library

我有一个声明的界面

Task DoSomethingAsync();
Run Code Online (Sandbox Code Playgroud)

我正在使用MoqFramework进行测试:

[TestMethod()]
public async Task MyAsyncTest()
{
   Mock<ISomeInterface> mock = new Mock<ISomeInterface>();
   mock.Setup(arg => arg.DoSomethingAsync()).Callback(() => { <my code here> });
   ...
}
Run Code Online (Sandbox Code Playgroud)

然后在我的测试中我执行调用的代码await DoSomethingAsync().而且测试在这条线上失败了.我究竟做错了什么?

Pan*_*vos 634

您的方法没有任何回调,因此没有理由使用.CallBack().您可以使用.Returns()Task.FromResult简单地返回具有所需值的任务,例如:

MyType someValue=...;
mock.Setup(arg=>arg.DoSomethingAsync())        
    .Returns(Task.FromResult(someValue));
Run Code Online (Sandbox Code Playgroud)

更新2014-06-22

Moq 4.2有两种新的扩展方法可以帮助解决这个问题.

mock.Setup(arg=>arg.DoSomethingAsync())
    .ReturnsAsync(someValue);

mock.Setup(arg=>arg.DoSomethingAsync())        
    .ThrowsAsync(new InvalidOperationException());
Run Code Online (Sandbox Code Playgroud)

更新2016-05-05

正如Seth Flowers在另一个答案中提到的,ReturnsAsync仅适用于返回a的方法Task<T>.对于仅返回Task的方法,

.Returns(Task.FromResult(default(object)))
Run Code Online (Sandbox Code Playgroud)

可以使用.

本回答所示,在.NET 4.6中,这简化为.Returns(Task.CompletedTask);,例如:

mock.Setup(arg=>arg.DoSomethingAsync())        
    .Returns(Task.CompletedTask);
Run Code Online (Sandbox Code Playgroud)

  • .Returns(Task.CompletedTask); 这是我的答案 (14认同)
  • 感谢您将此答案保持最新,因为Moq框架已收到更新! (7认同)

Set*_*ers 38

类似问题

我的界面看起来大致如下:

Task DoSomething(int arg);
Run Code Online (Sandbox Code Playgroud)

症状

我的单元测试失败,当我的服务测试awaited调用DoSomething.

固定

不同于接受的答案,你是无法呼叫.ReturnsAsync()Setup()在这种情况下这种方法,因为该方法返回的非泛型Task,而不是Task<T>.

但是,您仍然可以.Returns(Task.FromResult(default(object)))在设置上使用,允许测试通过.


小智 26

您只需要.Returns(Task.FromResult(0));在回调后添加.

例:

mock.Setup(arg => arg.DoSomethingAsync())
    .Callback(() => { <my code here> })
    .Returns(Task.FromResult(0));
Run Code Online (Sandbox Code Playgroud)