使用 IMemoryCache 扩展方法的单元测试方法

Unit testing method that uses IMemoryCache extension method

我正在尝试使用 MSTest 和 Moq 为使用 IMemoryCache 扩展方法的方法编写单元测试。情况:

public class ClassToTest
{        
  private IMemoryCache Cache { get; }

  public ClassToTest(IMemoryCache cache)
  {          
    Cache = cache;
  }

  public async Task<SomeType> MethodToTest(string key)
  {
    // Get is an extension method defined in Microsoft.Extensions.Caching.Memory
    var ci = Cache.Get<CachedItem<T>>(key);

    // Do stuff with cached item
  }
}

如何对它进行单元测试?

到目前为止我试过:

[TestMethod]
public void TestMethodToTest()
{
  IServiceCollection services = new ServiceCollection();
  services.AddMemoryCache();

  var serviceProvider = services.BuildServiceProvider();
  var memoryCache = serviceProvider.GetService<IMemoryCache>();

  ClassToTest testClass = new ClassToTest(memoryCache);
}

这给了我以下错误:“'IServiceCollection' 不包含 'AddMemoryCache' 的定义并且没有可访问的扩展方法 'AddMemoryCache' 接受类型为 'IServiceCollection' 的第一个参数可以找到(您是否缺少 using 指令或程序集引用?)”。

有谁知道如何对该方法进行单元测试?最好不改变方法本身。 有没有标准的方法来做到这一点? 提供任何帮助。

我认为你必须修改 ClassToTest。您可以有一个类型为 Func<string, CachedItem<T>> 的 属性,它被指定使用您的 class' 构造函数中的扩展:

public Func<string, CachedItem<T>> GetFromCache { get; set; }
public ClassToTest(IMemoryCache cache)
{          
    Cache = cache;
    GetFromCache = key => Cache.Get<CachedItem<T>>(key);
}

然后,当您想要测试 class 时,您可以通过以下语句覆盖该行为:

ClassToTest testClass = new ClassToTest(memoryCache);
testClass.GetFromCache = key => /* something else */;

一般来说,扩展方法仍然只是静态方法的语法糖,因此像 ClassToTest 那样使用它们会引入依赖关系并使代码更难单独测试。