首页 > 解决方案 > 如何在集成测试之间刷新 IAppCache

问题描述

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

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

我的猜测是为每个测试重新创建类实例,但静态数据是共享的;并且缓存是静态的。我在缓存上看不到任何“刷新”方法。

标签: c#asp.net.netunit-testingintegration-testing

解决方案


正如我在我的 OP 评论中提到的 LazyCache afaik 没有明确的操作或任何本机来核对缓存。但是,我认为您可以使用一些选项。

  • 使用 Remove 在每次测试之前/之后实现一个方法以删除缓存条目;
  • 为不在测试之间保留缓存的测试提供不同的 LazyCache 缓存提供程序
  • 深入 LazyCache,获取底层缓存提供程序,看看是否有任何方法可以清除缓存条目

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

默认情况下,LazyCache 使用MemoryCache作为缓存提供程序。MemoryCache 也没有明确的清除操作,但是当紧凑百分比设置为 1.0 时, Compact看起来基本上可以清除缓存。要访问它,您需要从 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 小时。


推荐阅读