如何在模拟的异步方法上设置可验证的期望?

时间:2016-04-05 14:07:24

标签: async-await moq stackexchange.redis

我尝试使用Moq来测试WebAPI控制器和Redis数据库之间的集成,使用StackExchange.Redis客户端,并且无法确定如何在包含a的模拟异步方法上设置可验证的期望回调或其他一些断言行为。

通常,我使用以下语法:

const string KEY = "some_key";
var db = new Mock<IDatabase>();
db.Setup(d => d.HashSetAsync(KEY, It.IsAny<HashEntry[]>(),It.IsAny<CommandFlags>()))
    .Callback<RedisKey,HashEntry[],CommandFlags>((key, hash, flags) => {
                hash.ShouldContain(entry => entry.Name == "customerid");
                hash.ShouldContain(entry => entry.Name == "quotenumber");
     })
     .Verifiable();

但是这给了我:

  

&#39;&Moq.Language.Flow.IReturnsThrows LT; StackExchange.Redis.IDatabase,System.Threading.Tasks.Task&GT;&#39;不包含&#39;可验证&#39;的定义。并且没有可扩展的方法&#39;可验证的&#39;接受第一个类型&#39; Moq.Language.Flow.IReturnsThrows&#39;可以找到(你错过了使用指令或程序集引用吗?)

如果我在db.HashSetAsync调用中将db.HashSet更改为Setup,则按预期工作。似乎在常规方法上设置Call​​back会返回ICallbackResult,但在异步方法调用上设置回调会返回IReturnsThrows - 我不确定如何将其中一个标记为验证。有什么想法吗?

1 个答案:

答案 0 :(得分:8)

对于异步方法,您需要在使用回调之前从设置中返回已完成的Task

看看这里:

Using Moq to mock an asynchronous method for a unit test

  

你正在创建一个任务但从未启动它,所以它永远不会   完成。但是,不要只是启动任务 - 而是改为   使用Task.FromResult<TResult>将给你一个任务   已经完成:

这是有效的

const string KEY = "some_key";
var db = new Mock<IDatabase>();
db.Setup(d => d.HashSetAsync(KEY, It.IsAny<HashEntry[]>(), It.IsAny<CommandFlags>()))
    .Returns(Task.FromResult<object>(null))
    .Callback<RedisKey, HashEntry[], CommandFlags>((key, hash, flags) => {
        hash.ShouldContain(entry => entry.Name == "customerid");
        hash.ShouldContain(entry => entry.Name == "quotenumber");
    })
    .Verifiable();