I'm trying to mock IMemoryCache
with Moq. I'm getting this error:
An exception of type 'System.NotSupportedException' occurred in
Moq.dll but was not handled in user codeAdditional information: Expression references a method that does not
belong to the mocked object: x => x.Get<String>(It.IsAny<String>())
My mocking code:
namespace Iag.Services.SupplierApiTests.Mocks
{
public static class MockMemoryCacheService
{
public static IMemoryCache GetMemoryCache()
{
Mock<IMemoryCache> mockMemoryCache = new Mock<IMemoryCache>();
mockMemoryCache.Setup(x => x.Get<string>(It.IsAny<string>())).Returns("");<---------- **ERROR**
return mockMemoryCache.Object;
}
}
}
Why do I get that error?
This is the code under test:
var cachedResponse = _memoryCache.Get<String>(url);
Where _memoryCache
is of type IMemoryCache
How do I mock the _memoryCache.Get<String>(url)
above and let it return null?
Edit: How would I do the same thing but for _memoryCache.Set<String>(url, response);
? I don't mind what it returns, I just need to add the method to the mock so it doesn't throw when it is called.
Going by the answer for this question I tried:
mockMemoryCache
.Setup(m => m.CreateEntry(It.IsAny<object>())).Returns(null as ICacheEntry);
Because in the memoryCache extensions it shows that it uses CreateEntry
inside Set
. But it is erroring out with "object reference not set to an instance of an object".
Best Answer
According to source code for MemoryCacheExtensions.cs,
The
Get<TItem>
extension method makes use of the followingNotice that essentially it is using the
TryGetValue(Object, out Object)
method.Given that it is not feasible to mock extension methods with Moq, Try mocking the interface members that are accessed by the extension methods.
Referring to Moq's quickstart update
MockMemoryCacheService
to properly setup theTryGetValue
method for the test.From comments
Here is an example using the modified service of how to mock the
memoryCache.Get<String>(url)
and let it returnnull
UPDATE
The same process can be applied for the
Set<>
extension method which looks like this.This method makes use of the
CreateEntry
method which returns aICacheEntry
which is also acted upon. So set up the mock to return a mocked entry as well like in the following example