如何在模拟的异步方法上设置可验证的期望?
How do I set up a verifiable expectation on a mocked async method?
我正在尝试使用 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();
但这给了我:
'Moq.Language.Flow.IReturnsThrows<StackExchange.Redis.IDatabase,System.Threading.Tasks.Task>' does not contain a definition for 'Verifiable' and no extension method 'Verifiable' accepting a first argument of type 'Moq.Language.Flow.IReturnsThrows' could be found (are you missing a using directive or an assembly reference?)
如果我在 Setup
调用中将 db.HashSetAsync
更改为 db.HashSet
,它将按预期工作。似乎在常规方法 returns 和 ICallbackResult
上设置回调,但在异步方法调用 returns 和 IReturnsThrows
上设置回调 - 我不确定如何您将其中一个标记为可验证。有什么想法吗?
对于异步方法,在使用回调
之前,您需要从设置中return完成Task
看这里:
Using Moq to mock an asynchronous method for a unit test
You're creating a task but never starting it, so it's never
completing. However, don't just start the task - instead, change to
using Task.FromResult<TResult>
which will give you a task which has
already completed:
这有效
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();
我正在尝试使用 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();
但这给了我:
'Moq.Language.Flow.IReturnsThrows<StackExchange.Redis.IDatabase,System.Threading.Tasks.Task>' does not contain a definition for 'Verifiable' and no extension method 'Verifiable' accepting a first argument of type 'Moq.Language.Flow.IReturnsThrows' could be found (are you missing a using directive or an assembly reference?)
如果我在 Setup
调用中将 db.HashSetAsync
更改为 db.HashSet
,它将按预期工作。似乎在常规方法 returns 和 ICallbackResult
上设置回调,但在异步方法调用 returns 和 IReturnsThrows
上设置回调 - 我不确定如何您将其中一个标记为可验证。有什么想法吗?
对于异步方法,在使用回调
之前,您需要从设置中return完成Task
看这里:
Using Moq to mock an asynchronous method for a unit test
You're creating a task but never starting it, so it's never completing. However, don't just start the task - instead, change to using
Task.FromResult<TResult>
which will give you a task which has already completed:
这有效
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();