如何告诉Moq返回任务?


327

我有一个接口声明

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()。测试只是失败了。我究竟做错了什么?


5
当您说那条线上的测试错误时,它将产生什么错误?
AlSki 2014年

@AlSki可能是NullReferenceException。你可以看到在这里
LuckyLikey

Answers:


709

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

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在另一个答案中提到的那样,ReturnsAsync仅适用于返回a的方法Task<T>。对于仅返回Task的方法,

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

可以使用。

如此答案所示,在.NET 4.6中,它简化为.Returns(Task.CompletedTask);

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

16
.Returns(Task.CompletedTask); 那就是我的答案
Todd Vance

8
感谢您在Moq框架已收到更新的情况下使此答案保持最新!
Jacob Stamm '18

.Returns(Task.FromResult(default(object))当返回类型为void时,效果很好。 .Returns(Task.FromResult(null as MyType))当期望的返回类型为null时,效果很好。
杰里米·雷·布朗

1
正如我所解释的,@ JeremyRayBrown default(object)不再需要.NET 4.6 。null as MyType是一样的default(MyType),只要MyType是一个引用类型。
Panagiotis Kanavos

40

类似问题

我有一个大致类似的界面:

Task DoSomething(int arg);

病征

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

固定

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

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


1
对此,请考虑一下,如果您需要返回一个非通用任务(非.net 4.6),我会考虑将Task.Delay(1)作为返回Task的简便方法。您也可以通过增加时间参数来模仿工作。
stevethethread '16

26

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

例:

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

4

现在您还可以使用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());
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.