Reputation: 5062
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>();
in the test
AddItemFactory has the following signature:
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:
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.
Upvotes: 1
Views: 1701
Reputation: 3193
That GetOrAddAsync method overload is an extension method; 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:
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:
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.
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.
Upvotes: 2