c# - 测试 ASP.NET Core IMemoryCache 的正确方法

标签 c# asp.net-core moq extension-methods .net-core

我正在编写一个简单的测试用例来测试我的 Controller 在调用我的服务之前调用缓存。我正在使用 xUnit 和 Moq 来完成这项任务。

我遇到了一个问题,因为 GetOrCreateAsync<T>是一种扩展方法,框架不能模拟这些方法。我依靠内部细节来弄清楚我可以模拟 TryGetValue相反,逃避我的测试(参见 https://github.com/aspnet/Caching/blob/c432e5827e4505c05ac7ad8ef1e3bc6bf784520b/src/Microsoft.Extensions.Caching.Abstractions/MemoryCacheExtensions.cs#L116 )

[Theory, AutoDataMoq]
public async Task GivenPopulatedCacheDoesntCallService(
    Mock<IMemoryCache> cache,
    SearchRequestViewModel input,
    MyViewModel expected)
{
    object expectedOut = expected;
    cache
        .Setup(s => s.TryGetValue(input.Serialized(), out expectedOut))
        .Returns(true);
    var sut = new MyController(cache.Object, Mock.Of<ISearchService>());
    var actual = await sut.Search(input);
    Assert.Same(expected, actual);
}

我无法接受我正在查看 MemoryCache 实现细节并且它可以随时更改的事实。

供引用,这是 SUT 代码:

public async Task<MyViewModel> Search(SearchRequestViewModel request)
{
    return await cache.GetOrCreateAsync(request.Serialized(), (e) => search.FindAsync(request));
}

您会推荐任何不同的测试吗?

最佳答案

老实说,我建议根本不要测试这种交互。

我会以不同的方式处理这个测试用例:您真正关心的是,一旦您的 Controller 从您的 ISearchService 检索到数据,它就不应该再次请求数据,并且应该从之前的通话。

IMemoryCache 在后台使用的事实只是一个实现细节。我什至懒得为它设置一个测试替身,我只会使用 Microsoft.Extensions.Caching.Memory.MemoryCache 对象的一个​​实例。

我的新测试看起来像这样:

[Theory]
public async Task GivenResultAlreadyRetrieved_ShouldNotCallServiceAgain()
{
    // Arrange
    var expected = new MyViewModel();

    var cache = new MemoryCache(new MemoryCacheOptions());
    var searchService = new Mock<ISearchService>();

    var input = new SearchRequestViewModel();

    searchService
        .SetupSequence(s => s.FindAsync(It.IsAny<SearchRequestViewModel>()))
        .Returns(Task.FromResult(expected))
        .Returns(Task.FromResult(new MyViewModel()));

    var sut = new MyController(cache, searchService.Object);

    // Act
    var resultFromFirstCall = await sut.Search(input);
    var resultFromSecondCall = await sut.Search(input);

    // Assert
    Assert.Same(expected, resultFromFirstCall);
    Assert.Same(expected, resultFromSecondCall);
}

关于c# - 测试 ASP.NET Core IMemoryCache 的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40684617/

相关文章:

c# - 如何将 Entity Framework 添加到控制台应用程序(包括图像)

c# - asp.net core DI - 我可以使服务依赖于其他服务吗

c# - 如何在单例类上使用 Moq,以便我们只能测试业务逻辑而忽略日志记录

C# 检测正在关闭的应用程序

c# - 将 C# 类转换为 JSON 表示的最佳方法

c# - .NET Core 2.1 - 构建时的 dotnet/exe,缺少包

mysql - 执行存储过程而不等待结果(Angular/.net core 2)

c# - 使用 Func<> 的 FindBy 方法的 Moq 存储库设置

c# - 无法让模拟方法返回 null

javascript - 将输入字段添加在一起并显示在标签中