简体   繁体   English

如何使用 It.IsAny AddItemFactory 函数模拟 IAppCache 的 GetOrAddAsync 方法

[英]How to mock IAppCache's GetOrAddAsync method with It.IsAny AddItemFactory function

The method I'm testing has this bit of code in it:我正在测试的方法中包含以下代码:

var devices = await _cache.GetOrAddAsync(_cacheKey, AddItemFactory, DateTimeOffset.Now.AddMinutes(Configuration.DeviceInMinutes));`

Where _cache is an IAppCache and is being mocked with a new Mock<IAppCache>();其中_cache是一个IAppCache并且正在被一个new Mock<IAppCache>(); in the test在测试中

AddItemFactory has the following signature: AddItemFactory 具有以下签名:

private async Task<IDictionary<int, Device>> AddItemFactory()

In my test I have written:在我的测试中,我写了:

        _appCache.Setup(x => x.GetOrAddAsync(
            It.IsAny<string>(),
            It.IsAny<Func<Task<IDictionary<int, Device>>>>(),
            It.IsAny<DateTimeOffset>())
        ).ReturnsAsync(fakeDictionary);

When that .Setup gets evaluated, my test crashes with the following error:当 .Setup 被评估时,我的测试崩溃并出现以下错误:

System.NotSupportedException : Invalid setup on an extension method: x => x.GetOrAddAsync<IDictionary<int, Device>>(It.IsAny<string>(), It.IsAny<Func<Task<IDictionary<int, Device>>>>(), It.IsAny<DateTimeOffset>())

I think it's mocked correctly because Visual Studio intellisense isn't complaining and signatures being wrong but I don't understand what is happening.我认为它被正确地嘲笑了,因为 Visual Studio 智能感知没有抱怨和签名是错误的,但我不明白发生了什么。

That GetOrAddAsync method overload is an extension method; GetOrAddAsync 方法重载是一个扩展方法; extension methods cannot be mocked.扩展方法不能被模拟。

GetOrAddAsync<T>(
      this IAppCache cache,
      string key,
      Func<Task<T>> addItemFactory,
      DateTimeOffset expires)

You need to mock the following method on the IAppCache interface:您需要在IAppCache接口上模拟以下方法:

Task<T> GetOrAddAsync<T>(string key, Func<ICacheEntry, Task<T>> addItemFactory);

If you want to use Moq to do this, the library LazyCache.Testing.Moq (disclaimer - I am the author) implements this via the following setup:如果您想使用 Moq 来执行此操作,库LazyCache.Testing.Moq (免责声明 - 我是作者)通过以下设置来实现:

cachingServiceMock.Setup(m => m.GetOrAddAsync(
    It.IsAny<string>(),
    It.IsAny<Func<ICacheEntry, Task<T>>>()))    
    .Returns(Task.FromResult(cacheEntryValue));

where cacheEntryValue is the task result value an invocation should return.其中cacheEntryValue是调用应返回的任务结果值。

If you don't need to use Moq, given you are using a GetOrAdd* method, you should be able to use the built-in fake ( MockCachingService ) provided by the LazyCache library as per the doco .如果您不需要使用 Moq,假设您使用的是 GetOrAdd* 方法,您应该能够使用由 LazyCache 库根据doco提供的内置伪造( MockCachingService )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM