[英]How can I tell Moq to return a Task?
我有一个声明的接口
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()
的代码。 而测试只是在那条线上失败了。 我究竟做错了什么?
您的方法没有任何回调,因此没有理由使用.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 在另一个答案中提到的, ReturnsAsync
仅适用于返回Task<T>
。 对于只返回一个 Task 的方法,
.Returns(Task.FromResult(default(object)))
可以使用。
如本答案所示,在 .NET 4.6 中,这被简化为.Returns(Task.CompletedTask);
,例如:
mock.Setup(arg=>arg.DoSomethingAsync())
.Returns(Task.CompletedTask);
类似问题
我有一个大致如下所示的界面:
Task DoSomething(int arg);
症状
当我的被测服务awaited
调用DoSomething
时,我的单元测试失败。
使固定
与接受的答案不同,在这种情况下,您无法在此方法的Setup()
.ReturnsAsync()
上调用.ReturnsAsync()
,因为该方法返回的是非通用Task
,而不是Task<T>
。
但是,您仍然可以在设置中使用.Returns(Task.FromResult(default(object)))
,从而允许测试通过。
你只需要添加.Returns(Task.FromResult(0));
回调后。
例子:
mock.Setup(arg => arg.DoSomethingAsync())
.Callback(() => { <my code here> })
.Returns(Task.FromResult(0));
现在你也可以使用 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());
感谢接受的答案提供了一个非常有用的解决方案。
我在我们的项目中添加了两个扩展方法(用于Task
和ValueTask
),以便习惯于在所有异步设置上调用.ReturnsAsync
的人们更容易发现它。
public static class MoqExtensions
{
public static IReturnsResult<TMock> ReturnsAsync<TMock>(this IReturns<TMock, Task> mock)
where TMock : class
{
return mock.Returns(Task.CompletedTask);
}
public static IReturnsResult<TMock> ReturnsAsync<TMock>(this IReturns<TMock, ValueTask> mock)
where TMock : class
{
return mock.Returns(ValueTask.CompletedTask);
}
}
可以这样调用:
mock.Setup(x => x.DoSomethingAsync())
.ReturnsAsync();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.