Asp.Net 核心:为集成测试重置 memoryCache
Asp.Net Core: reset memoryCache for Integration Tests
我已经创建了一些基本的集成测试来调用我的 Api 并查看权限是否正常工作。现在我遇到了一个问题,其中 运行 宁更多的所有测试其中一个失败 - 如果 运行 分开,它不会。
原因是,我使用 IMemoryCache 来存储用户登录后的某些权限。但是对于我的集成测试,权限存储在缓存中,当我尝试更改它们以进行测试时,它们是未刷新。
一般来说,有没有办法让每个集成测试的 MemoryCache 失效?
我的一个集成测试 class 基本上是这样做的:
public IntegrationTest(CustomWebApplicationFactory<Namespace.Startup> factory)
{
_factory = factory;
_client = _factory.CreateClient();
// init the DB here etc...
var response = await _client.GetAsync("api/Some/Path");
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
}
有没有办法告诉工厂不要使用缓存或使用模拟缓存或类似的东西?
编辑:
缓存在我的 startup.cs 中设置如下:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMemoryCache();
[...]
}
}
这是通过 DependenyInjection 注入到我的控制器中的,就像这样:
private IMemoryCache _cache;
private MemoryCacheEntryOptions _cacheOptions;
const int CACHE_LIFETIME_IN_DAYS = 7;
public SomeController(IMemoryCache cache) {
_cache = cache;
_cacheOptions = new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromDays(CACHE_LIFETIME_IN_DAYS));
}
我在我的控制器中使用它与 _cache.TryGetValue
和 _cache.Set
作为快速修复,您可以尝试这样做:
var memoryCache = _factory.Services.GetService<IMemoryCache>() as MemoryCache;
memoryCache.Compact(1.0);
当您需要重置缓存时。
但我建议要么考虑在测试之间不共享 _factory
(尽管它可能会对性能产生影响),要么考虑覆盖(就像 done in the docs 与上下文一样)IMemoryCache
到你可以根据需要在外面控制的东西。
UPD
由于默认情况下测试不是 运行 并行,您可以手动注册 MemoryCache
的实例。像这样:
public class CustomWebApplicationFactory<TStartup>
: WebApplicationFactory<TStartup> where TStartup : class
{
internal readonly MemoryCache MemoryCache;
public CustomWebApplicationFactory()
{
MemoryCache = new MemoryCache(new MemoryCacheOptions());
}
public void ClearCache() => MemoryCache.Compact(1.0);
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(services =>
{
var descriptor = services.SingleOrDefault(
d => d.ServiceType ==
typeof(IMemoryCache));
services.Remove(descriptor);
services.AddSingleton<IMemoryCache>(MemoryCache);
});
}
}
并在测试中调用 factory.ClearCache()
:
public void Test1()
{
var factory = new CustomWebApplicationFactory<Startup>();
var memoryCache = factory.Services.GetService<IMemoryCache>() as MemoryCache;
memoryCache.Set("test", "test");
factory.ClearCache();
Assert.IsFalse(memoryCache.TryGetValue("test", out var val));
}
如果您需要 运行 并行测试同一个工厂(尽管我会说最好只创建不同的工厂),那么您可以创建 IMemoryCache
实现,它将以某种方式确定(例如在客户端请求中传递一些特定的 header)不同的测试 运行s 和 return 不同的 MemoryCache
实例。
我已经创建了一些基本的集成测试来调用我的 Api 并查看权限是否正常工作。现在我遇到了一个问题,其中 运行 宁更多的所有测试其中一个失败 - 如果 运行 分开,它不会。
原因是,我使用 IMemoryCache 来存储用户登录后的某些权限。但是对于我的集成测试,权限存储在缓存中,当我尝试更改它们以进行测试时,它们是未刷新。
一般来说,有没有办法让每个集成测试的 MemoryCache 失效?
我的一个集成测试 class 基本上是这样做的:
public IntegrationTest(CustomWebApplicationFactory<Namespace.Startup> factory)
{
_factory = factory;
_client = _factory.CreateClient();
// init the DB here etc...
var response = await _client.GetAsync("api/Some/Path");
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
}
有没有办法告诉工厂不要使用缓存或使用模拟缓存或类似的东西?
编辑:
缓存在我的 startup.cs 中设置如下:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMemoryCache();
[...]
}
}
这是通过 DependenyInjection 注入到我的控制器中的,就像这样:
private IMemoryCache _cache;
private MemoryCacheEntryOptions _cacheOptions;
const int CACHE_LIFETIME_IN_DAYS = 7;
public SomeController(IMemoryCache cache) {
_cache = cache;
_cacheOptions = new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromDays(CACHE_LIFETIME_IN_DAYS));
}
我在我的控制器中使用它与 _cache.TryGetValue
和 _cache.Set
作为快速修复,您可以尝试这样做:
var memoryCache = _factory.Services.GetService<IMemoryCache>() as MemoryCache;
memoryCache.Compact(1.0);
当您需要重置缓存时。
但我建议要么考虑在测试之间不共享 _factory
(尽管它可能会对性能产生影响),要么考虑覆盖(就像 done in the docs 与上下文一样)IMemoryCache
到你可以根据需要在外面控制的东西。
UPD
由于默认情况下测试不是 运行 并行,您可以手动注册 MemoryCache
的实例。像这样:
public class CustomWebApplicationFactory<TStartup>
: WebApplicationFactory<TStartup> where TStartup : class
{
internal readonly MemoryCache MemoryCache;
public CustomWebApplicationFactory()
{
MemoryCache = new MemoryCache(new MemoryCacheOptions());
}
public void ClearCache() => MemoryCache.Compact(1.0);
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(services =>
{
var descriptor = services.SingleOrDefault(
d => d.ServiceType ==
typeof(IMemoryCache));
services.Remove(descriptor);
services.AddSingleton<IMemoryCache>(MemoryCache);
});
}
}
并在测试中调用 factory.ClearCache()
:
public void Test1()
{
var factory = new CustomWebApplicationFactory<Startup>();
var memoryCache = factory.Services.GetService<IMemoryCache>() as MemoryCache;
memoryCache.Set("test", "test");
factory.ClearCache();
Assert.IsFalse(memoryCache.TryGetValue("test", out var val));
}
如果您需要 运行 并行测试同一个工厂(尽管我会说最好只创建不同的工厂),那么您可以创建 IMemoryCache
实现,它将以某种方式确定(例如在客户端请求中传递一些特定的 header)不同的测试 运行s 和 return 不同的 MemoryCache
实例。