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

Dyl*_*tie 4 moq async-await stackexchange.redis

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

通常,我使用以下语法:

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();
Run Code Online (Sandbox Code Playgroud)

但是这给了我:

'Moq.Language.Flow.IReturnsThrows <StackExchange.Redis.IDatabase,System.Threading.Tasks.Task>'不包含'Verifiable'的定义,也没有扩展方法'Verifiable'接受'Moq.Language'类型的第一个参数可以找到.Flow.IReturnsThrows'(你是否缺少using指令或程序集引用?)

如果我改变db.HashSetAsync,以db.HashSetSetup调用,它将按预期工作.似乎在常规方法上设置Call​​back会返回一个ICallbackResult但在异步方法调用上设置回调会返回IReturnsThrows- 而且我不确定如何将其中一个标记为可验证.有任何想法吗?

Nko*_*osi 8

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

看看这里:

使用Moq模拟单元测试的异步方法

你正在创建一个任务但从未启动它,所以它永远不会完成.但是,不要只是启动任务 - 而是更改为使用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();
Run Code Online (Sandbox Code Playgroud)