2016-12-06 73 views
1

我想模拟一个名为GetOrAddAsync的函数。它的定义为:Moq和异步使用LazyCache的乐趣

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 <>中传递的数据填充它。

我嘲讽的这种尝试至今如下:

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表达式键入“IEnumerable的”,因为它不是一个委托类型。

我的心,愿与这种语法:)

回答

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(); 
       }); 
+0

我太亲近:)。谢谢你的工作! – user441521

0

而不是必须使用Moq自己模拟LazyCache API,为什么不使用框架提供的模拟版本呢?它只是执行你的委托被缓存的任何东西,并且从不做任何缓存。退房MockCachingService.cs