c# - 将同步 Moq 模拟转换为异步

标签 c# moq async-await

我正在努力将大量同步 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/

相关文章:

C# 异步任务无限期等待

javascript - Node.js:全局变量是否在实例之间共享?

c# - C#-从类内部调用方法

c# - 命令模式 - 目的?

c# - Moq - 如何模拟属性但允许在 C# 中调用方法?

unit-testing - Moq - 如何对方法中引用的更改进行单元测试

javascript - 如何在异步函数内批量调用 React setState() ?

c# - 获取对 ASP.NET web.config customErrors 部分的引用

javascript - 覆盖 javascript 全局变量的可靠方法

c# - 使用 Moq 检查传递回 mock 的对象的属性