I'm unit testing a ClientService that uses the IMemoryCache
interface:
ClientService.cs:
public string Foo()
{
//... code
_memoryCache.Set("MyKey", "SomeValue", new TimeSpan(0, 0, 60));
}
When I try to mock the IMemoryCache
's Set
extension with:
AutoMock mock = AutoMock.GetLoose();
var memoryCacheMock = _mock.Mock<IMemoryCache>();
string value = string.Empty;
// Attempt #1:
memoryCacheMock
.Setup(x => x.Set<string>(It.IsAny<object>(), It.IsAny<string>(), It.IsAny<TimeSpan>()))
.Returns("");
// Attempt #2:
memoryCacheMock
.Setup(x => x.Set(It.IsAny<object>(), It.IsAny<object>(), It.IsAny<TimeSpan>()))
.Returns(new object());
It throw an exception of:
System.NotSupportedException: Unsupported expression: x => x.Set(It.IsAny(), It.IsAny(), It.IsAny()) Extension methods (here: CacheExtensions.Set) may not be used in setup / verification ex
This is the Cache extension of the namespace Microsoft.Extensions.Caching.Memory
public static class CacheExtensions
{
public static TItem Set<TItem>(this IMemoryCache cache, object key, TItem value, TimeSpan absoluteExpirationRelativeToNow);
}
Remember that the extension method cannot be mocked; unit tests for a class that is using it will test both this class logic and extension method's logic.
Extension methods are ways for developers to "add on" methods to objects they can't control. For instance, if you wanted to add a "DoSomething()" method to the System. Windows. Forms object, since you don't have access to that code, you would simply create an extension method for the form with the following syntax.
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 the TryGetValue method for the test.
Extension methods are actually static methods and they cannot be mocked using moq. What you could mock are the methods used by the extension method itself... In your case Set uses CreateEntry which is the method defined by IMemoryCache and it could be mocked.
public static class CacheExtensions { public static TItem Set<TItem> (this IMemoryCache cache, object key, TItem value, TimeSpan absoluteExpirationRelativeToNow); } You cannot mock extension method, I guess behind the Set is actually CreateEntry which actually should have been mocked...
Mocking extension methods is one of the advanced features supported in Telerik® JustMock. In this topic, we will go through some examples that show how easy and straightforward it is to assert expectations related to extension methods in your tests. This feature is available only in the commercial version of Telerik JustMock.
Is there a way to mock the ExecuteSQLCommand method directly? It is not possible to mock it directly as it is an extension method. It is possible to mock what that extension method invokes though and mock it indirectly. I had a similar case and ended up implementing EntityFrameworkCore.Testing as it's a pretty involved Moq set up.
Extension methods are actually static methods and they cannot be mocked using moq
. What you could mock are the methods used by the extension method itself...
In your case Set
uses CreateEntry
which is the method defined by IMemoryCache
and it could be mocked. Try something like this:
memoryCacheMock
.Setup(x => x.CreateEntry(It.IsAny<object>()))
.Returns(Mock.Of<ICacheEntry>);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With