Мой сервисный код ниже:

var cachedLatestVersion = await _cache.GetOrAddAsync("latestVersion", latestVersion, DateTimeOffset.Now.AddHours(24));

Я попытался имитировать интерфейс IAppache и установить значение для метода GetOrAddAsync, но произошла ошибка

_cacheMock.Setup(c => c.GetOrAddAsync(It.IsAny<string>(), It.IsAny<Func<Task<string>>>(), It.IsAny<DateTimeOffset>())).ReturnsAsync("latestVersion");

Ошибка:

System.NotSupportedException: неподдерживаемое выражение: c => c.GetOrAddAsync (It.IsAny (), It.IsAny > (), It.IsAny ()) Методы расширения (здесь: AppCacheExtensions.GetOrAddAsync) не могут быть используется в выражениях настройки / проверки.

Затем я придумал другое решение, которое создает новый экземпляр MockCachingService ():

var mockedCache = new MockCachingService(); var cacheMock = Mock.Get(mockedCache);

Но у меня ошибка другого типа

System.ArgumentException: экземпляр объекта не был создан Moq. (Параметр 'mocked')

0
Mery 15 Фев 2021 в 19:30

1 ответ

Лучший ответ

Вы не можете имитировать расширения, вам нужно будет имитировать член интерфейса, который вызывается в расширении. Вам нужно будет его осмотреть, но предположим, что это будет одно из следующих:

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

Источник: https://github.com/alastairtree/LazyCache/blob/ master / LazyCache / IAppCache.cs

Наверное, второй:

_cacheMock.Setup(c => c.GetOrAddAsync(It.IsAny<string>(), It.IsAny<Func<ICacheEntry, Task<string>>>(), It.IsAny<MemoryCacheEntryOptions>())).ReturnsAsync("latestVersion");

Включенный в библиотеку сервис кеширования макетов - это не макет Moq, а скорее поддельная реализация. Вот почему Mock.Get не будет работать с ним.

В качестве альтернативы вики-статья о модульном тестировании описывает альтернативные варианты использования. это может подойти, например, использовать настоящую вещь. Для тестов, использующих последний, я использую следующее, чтобы очищать кеш после каждого теста:

[TearDown]
public void TearDown()
{
   var cacheProvider = CachingService.CacheProvider;
   var memoryCache = (MemoryCache) cacheProvider.GetType().GetField("cache", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(cacheProvider);
   memoryCache.Compact(1.0);
}

Если вы хотите продолжить издевательство над службой кеширования, библиотека LazyCache.Testing (отказ от ответственности: я автор) предлагает простые готовые реализации для Moq и NSubstitute, которые позволят вам утверждать вызовы.

1
rgvlee 16 Фев 2021 в 03:00