使用 LazyCache 的最小起订量和异步乐趣
Moq and Async fun using LazyCache
我正在尝试模拟一个名为 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);
所以基本上,如果密钥存在,它会 return 里面有什么,如果不存在,它会创建一个密钥并用 return 从传入的 Func<> 中编辑的数据填充它。
到目前为止,我对此的模拟尝试如下:
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();
});
但是,这是 return 错误:
无法将 lambda 表达式转换为类型 'IEnumerable',因为它不是委托类型。
我的头脑已经准备好用这个语法爆炸了:)
当你有一个异步回调函数时,不要使用 ReturnsAsync,把它想象成 .ReturnsAsync(foo)
只是 shorthand 对 .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();
});
与其自己使用 Moq 模拟 LazyCache API 为什么不直接使用框架提供的模拟版本?它只执行要缓存的任何委托,从不执行任何缓存。查看 MockCachingService.cs
除了实际模拟缓存调用之外,我会通过为被测服务提供 CachingService 实例来保留缓存功能。
来源:Codidact
我正在尝试模拟一个名为 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);
所以基本上,如果密钥存在,它会 return 里面有什么,如果不存在,它会创建一个密钥并用 return 从传入的 Func<> 中编辑的数据填充它。
到目前为止,我对此的模拟尝试如下:
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();
});
但是,这是 return 错误:
无法将 lambda 表达式转换为类型 'IEnumerable',因为它不是委托类型。
我的头脑已经准备好用这个语法爆炸了:)
当你有一个异步回调函数时,不要使用 ReturnsAsync,把它想象成 .ReturnsAsync(foo)
只是 shorthand 对 .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();
});
与其自己使用 Moq 模拟 LazyCache API 为什么不直接使用框架提供的模拟版本?它只执行要缓存的任何委托,从不执行任何缓存。查看 MockCachingService.cs
除了实际模拟缓存调用之外,我会通过为被测服务提供 CachingService 实例来保留缓存功能。
来源:Codidact