我试图模拟一个名为GetOrAddAsync的函数。它被定义为:
Task<T> GetOrAddAsync<T>(string key, Func<Task<T>> addItemFactory, DateTimeOffset expires);
当我在实际代码中使用它时,我使用它:
DateTimeOffset cacheTimeout = new DateTimeOffset(DateTime.Now.AddHours(config.CacheHours));
Func<Task<IEnumerable<int>>> func = async () => await (from s in dbContext.Names select s.First).ToListAsync();
return await cache.GetOrAddAsync(key, func, cacheTimeout);
所以基本上如果密钥存在,它将返回其中的内容,如果不存在,它将创建一个密钥并用传入的Func&lt;&gt;返回的数据填充它。
到目前为止,我对此的嘲弄尝试如下:
cache.Setup(x => x.GetOrAddAsync(It.IsAny<string>(), It.IsAny<Func<Task<IEnumerable<int>>>>(), It.IsAny<DateTimeOffset>()))
.ReturnsAsync(async (string key, Func<Task<IEnumerable<int>>> func, DateTimeOffset policy) =>
{
return await func.Invoke();
});
但是,这会返回错误:
无法将lambda表达式转换为类型&#39; IEnumerable&#39;因为它不是代表类型。
我的思绪已准备好用这种语法爆炸:)
答案 0 :(得分:2)
当您拥有异步回调函数时,不会使用ReturnsAsync,更多地考虑它,因为.ReturnsAsync(foo)
只是.Returns(Task.FromResult(foo))
的简写。所以你要做的就是
cache.Setup(x => x.GetOrAddAsync(It.IsAny<string>(), It.IsAny<Func<Task<IEnumerable<int>>>>(), It.IsAny<DateTimeOffset>()))
.Returns(Task.FromResult(async (string key, Func<Task<IEnumerable<int>>> func, DateTimeOffset policy) =>
{
return await func.Invoke();
}));
更改为使用普通Returns(
,您的功能应该可以正常工作。
cache.Setup(x => x.GetOrAddAsync(It.IsAny<string>(), It.IsAny<Func<Task<IEnumerable<int>>>>(), It.IsAny<DateTimeOffset>()))
.Returns(async (string key, Func<Task<IEnumerable<int>>> func, DateTimeOffset policy) =>
{
return await func.Invoke();
});
答案 1 :(得分:0)
为什么不使用框架提供的模拟版本,而不是自己使用Moq模拟LazyCache API?它只执行您要缓存的任何代理,并且永远不会执行任何缓存。查看MockCachingService.cs