【问题标题】:Mocking of extension method result in System.NotSupportedException模拟扩展方法导致 System.NotSupportedException
【发布时间】:2020-01-02 10:45:17
【问题描述】:

我正在对使用 IMemoryCache 接口的 ClientService 进行单元测试:

ClientService.cs:

public string Foo()
{        
    //... code

    _memoryCache.Set("MyKey", "SomeValue", new TimeSpan(0, 0, 60));
}

当我尝试使用以下命令模拟 IMemoryCacheSet 扩展时:

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());

它抛出一个异常:

System.NotSupportedException:不支持的表达式:x => x.Set(It.IsAny(), It.IsAny(), It.IsAny()) 扩展方法(此处为:CacheExtensions.Set)可能无法在设置/验证中使用

这是命名空间Microsoft.Extensions.Caching.Memory的缓存扩展

public static class CacheExtensions
{
   public static TItem Set<TItem>(this IMemoryCache cache, object key, TItem value, TimeSpan absoluteExpirationRelativeToNow);
}

【问题讨论】:

  • 你不能模拟扩展方法,我猜Set后面实际上是CreateEntry,实际上应该被模拟...
  • 扩展方法是静态的——你不能模拟静态方法。我认为有一些工具可以让你替换它们,但恕我直言,这不是正确的方法。见here

标签: c# .net-core mocking moq extension-methods


【解决方案1】:

扩展方法实际上是静态方法,不能使用 moq 进行模拟。您可以模拟的是扩展方法本身使用的方法...

在您的情况下,Set 使用CreateEntry,这是IMemoryCache 定义的方法,它可以被模拟。试试这样的:

memoryCacheMock
    .Setup(x => x.CreateEntry(It.IsAny<object>()))
    .Returns(Mock.Of<ICacheEntry>);

【讨论】:

  • Get 方法怎么样?我假设它是 TryGetValue 方法?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多