我有一个声明
的界面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()
的代码。而且测试在这条线上失败了。我做错了什么?
答案 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());