如何在集成测试之间刷新 IAppCache

How to Flush IAppCache Between Integration Tests

我运行在 ASP.NET 中使用 xUnit 进行集成测试,其中之一确保多次查询数据只会导致对服务器的 1 次查询。如果我 运行 单独进行此测试,那么它就可以工作。如果我 运行 所有的测试,那么服务器被这个测试查询 0 次而不是 1 次。这表明由于其他测试结果已经在缓存中。

如何保证测试开始时IAppCache为空?我正在使用 LazyCache 实现。

我的猜测是 class 实例是为每个测试重新创建的,但是静态数据是共享的;并且缓存是静态的。我在缓存中没有看到任何 "flush" 方法。

正如我在 OP 评论中提到的,LazyCache afaik 没有明确的操作或任何原生的 nuke 缓存。不过,我认为您有几种选择。

  • 实现方法before/after 每次测试删除缓存条目,使用 Remove;
  • 为不在测试之间保留缓存的测试提供不同的 LazyCache 缓存提供程序
  • 深入研究 LazyCache,获取底层缓存提供程序并查看是否有任何方法来清除缓存条目

1 或 3 是我的选择。从测试的角度来看,1 意味着您需要了解所测试内容的内部结构。如果是我,我有点懒,可能会写几行来核对缓存。

默认情况下,LazyCache 使用 MemoryCache as the cache provider. MemoryCache doesn't have an explicit clear operation either but Compact 当压缩百分比设置为 1.0 时,看起来它基本上可以清除缓存。要访问它,您需要从 LazyCache 获取底层 MemoryCache 对象:

IAppCache cache = new CachingService();
var cacheProvider = cache.CacheProvider;
var memoryCache = (MemoryCache)cacheProvider.GetType().GetField("cache", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(cacheProvider);
memoryCache.Compact(1.0);

完整的 LINQPad 工作示例:

void Main()
{
    IAppCache cache = new CachingService();

    Console.WriteLine(cache.GetOrAdd("Foo", () => Foo.NewFoo, DateTimeOffset.Now.AddHours(1.0)));

    var cacheProvider = cache.CacheProvider;
    var memoryCache = (MemoryCache)cacheProvider.GetType().GetField("cache", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(cacheProvider);
    memoryCache.Compact(1.0);

    Console.WriteLine(cache.Get<Foo>("Foo"));
}

public class Foo
{
    public static Foo NewFoo
    {
        get
        {
            Console.WriteLine("Factory invoked");
            return new Foo();
        }
    }

    public override string ToString()
    {
        return "I am a foo";
    }
}

这导致以下每个 运行:

如果我删除紧凑调用,我们会得到以下结果:

这表明 Compact(1.0) 将核对缓存条目,即使有效期为 +1 小时。