我正在努力将大量同步 asp.net 代码转换为 .net 4.5 和新的异步语法。
我有很多测试代码,如下所示:
var retVal = new Foo(bar,baz);
_myMock.Setup(x => x.DoSomething(123)).Returns(retVal);
当我从 Foo DoSomething()
转换 DoSomething 的签名时至 async Task<Foo> DoSomething()
,我所有的测试代码都必须重写。我当前的解决方法是将原始代码转换为类似以下内容:
var retVal = new Foo(bar,baz);
_myMock.Setup(x => x.DoSomething(123))
.Returns(new Task<Foo>(()=>retVal));
这不是一个特别困难的转换,但是当我有成千上万的测试需要更新时,它会很乏味。
我尝试制作一个名为 ReturnsAsync 的扩展方法来执行 m 中的某些操作,但我遇到了一些我无法完全确定的类型推断问题。是否有标准或更简单的方法来转换这种模拟以更好地处理异步方法?
最佳答案
首先,命名:基于任务的异步模式 (TAP) 规定所有异步并返回 Task
的方法都应命名为以 Async
结尾。因此,您的方法应命名为 DoSomethingAsync
。
其次,Task
的构造函数创建了一个未启动的Task
,您必须手动Start()
它。如果您实际的 DoSomething
方法也执行此操作,那又不遵循 TAP,这意味着您的代码将无法与 await
一起正常工作。相反,您应该使用 Task.Run(() => value)
,或者更好的是,Task.FromResult(value)
。
第三,如果您向我们展示您运行不佳的代码会更好,以便我们可以告诉您您哪里出错了。
现在,ReturnsAsync()
扩展方法的主体非常简单,但我的大部分工作是找出正确的类型(特别是因为我不知道 Moq)。代码如下所示:
public static class MoqExtensions
{
public static IReturnsResult<TMock> ReturnsAsync<TMock, TResult>(
this IReturns<TMock, Task<TResult>> setup, TResult value)
where TMock : class
{
return setup.Returns(Task.FromResult(value));
}
}
关于c# - 将同步 Moq 模拟转换为异步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12081680/