从集成测试中植入种子时,.NET Core 3.1 IMemoryCache为空

问题描述

问题在于,由于搜索复杂,因此使用Entity Framework Core 3.1IMemoryCache的Web API。示例存储库:

public class UserRepository : IUserRepository
{
    private readonly IMemoryCache _cache;
    private readonly ApplicationDbContext _dbContext;

    public UserRepository(IMemoryCache cache,ApplicationDbContext dbContext)
    {
        _cache = cache;
        _dbContext = dbContext;
    }

    public async Task<List<UserCacheModel>> GetAll()
    {
        List<User> users = _cache.Get<List<User>>("users");
        if (users != null)
        {
            return UserMapper.MapToCacheModelList(users);
        }
        return await _dbContext.Users.ToListAsync();
    }

    public async Task<int> Insert(User user)
    {
        // Add to database
        _dbContext.Users.Add(user);
        await _dbContext.SaveChangesAsync();

        // Add to cache
        List<UserCacheModel> cachedUsers = _cache.Get<List<UserCacheModel>>("users");
        cachedUsers.Add(UserMapper.MapToCacheModel(user));
        }
    }

这是一个非常简单的示例,但是它使您清楚地知道如何使用它。为了进行复杂的测试,测试项目中有一个自定义的Web应用程序工厂,该工厂使用Startup.cs配置webhost,DI和所有内容。显然,DbContext已从DI中删除,并通过In-Memory DB切换到EF Core 3.1

问题是我想在此自定义Web应用程序工厂中植入应用内Memory Cache。它工作正常,但是当测试尝试插入用户时,它失败,因为 List<UserCacheModel> cachedUsers = _cache.Get<List<UserCacheModel>>("users");此行将为空。从Web应用程序工厂中植入的MemoryCache似乎与从DI中的UserRepository中解析的实例不同。

但是,如果我从工厂范围手动解析IMemoryCache,则可以看到启动时播种的数据。 DbContext已正确播种,除此以外一切正常

更新:

通过创建Microsoft.AspNetCore.Mvc.Testing自定义实现,通过WebApplicationFactory命名空间运行集成测试。这将创建一个Web应用程序,就像您调试自己的API时一样,因此,当您调用带有保存用户的请求的ActionMethod时,IMemoryCache是应用程序内缓存该新创建的Web应用程序就像一个docker容器,与您从集成测试代码中解析的应用程序不同。

至少我现在是这样想的。

有什么想法是最好的方法来获得应用内cache而不在应用中创建仅用于测试目的的假控制器?

解决方法

考虑在创建 WebApplicationFactory 后设置缓存,如下所示:

var factory = new MyWebApplicationFactory<Startup>();
var queriesClient = factory.CreateClient();
using var scope = factory.Services.CreateScope();
var memCache = scope.ServiceProvider.GetRequiredService<IMemoryCache>();
memCache.Set("Key",Value);

using HttpResponseMessage response = await queriesClient.GetAsync(new Uri(requestUri));

这将直接在工厂范围内设置缓存,现在就可以使用了。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...