我如何告诉Moq返回任务?

时间:2014-01-21 09:05:26

标签: c# unit-testing task-parallel-library moq

我有一个声明

的界面
Task DoSomethingAsync();

我正在使用MoqFramework进行测试:

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

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

4 个答案:

答案 0 :(得分:546)

您的方法没有任何回调,因此没有理由使用.CallBack()。您只需使用.Returns()Task.FromResult返回包含所需值的任务,例如:

MyType someValue=...;
mock.Setup(arg=>arg.DoSomethingAsync())        
    .Returns(Task.FromResult(someValue));

更新2014-06-22

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

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

mock.Setup(arg=>arg.DoSomethingAsync())        
    .ThrowsAsync(new InvalidOperationException());

更新2016-05-05

正如Seth Flowers在other answer中提到的那样,ReturnsAsync仅适用于返回Task<T>的方法。对于仅返回任务的方法,

.Returns(Task.FromResult(default(object)))

可以使用。

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

mock.Setup(arg=>arg.DoSomethingAsync())        
    .Returns(Task.CompletedTask);

答案 1 :(得分:35)

类似问题

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

Task DoSomething(int arg);

<强>症状

我的单位测试在我的服务awaited调用DoSomething时失败。

<强>修正

与接受的答案不同,在此方案中,您无法在.ReturnsAsync()此方法上调用Setup(),因为该方法返回非通用Task,而不是{{ 1}}。

但是,您仍然可以在设置中使用Task<T>,允许测试通过。

答案 2 :(得分:22)

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

示例:

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

答案 3 :(得分:3)

现在您还可以使用Talentsoft.Moq.SetupAsync包 https://github.com/TalentSoft/Moq.SetupAsync

基于此处找到的答案和向Moq提出的想法,但仍未在此处实现:https://github.com/moq/moq4/issues/384,大大简化了异步方法的设置

以前使用SetupAsync扩展程序完成的响应中找到的示例很少:

mock.SetupAsync(arg=>arg.DoSomethingAsync());
mock.SetupAsync(arg=>arg.DoSomethingAsync()).Callback(() => { <my code here> });
mock.SetupAsync(arg=>arg.DoSomethingAsync()).Throws(new InvalidOperationException());