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

标签 c# asp.net .net unit-testing integration-testing

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

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

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

最佳答案

正如我在 OP 评论中提到的,LazyCache afaik 没有明确的操作或任何本地内容来破坏缓存。不过,我认为您有几种选择。

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

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

默认情况下,LazyCache 使用 MemoryCache作为缓存提供者。 MemoryCache 也没有明确的清除操作,但 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";
    }
}

每次运行都会产生以下结果:

enter image description here

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

enter image description here

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

关于c# - 如何在集成测试之间刷新 IAppCache,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61739103/

相关文章:

c# - LINQ 聚合查询

c# - 如果某个进程在没有计时器的情况下运行,请执行某些操作

javascript - 访问 aspx 页面的客户端 javascript block 中由 RegisterClientScriptBlock 注入(inject)的 javascript 代码

c# - 如何使用 C# 在类文件中写入连接字符串?

.net - 异步任务方法的 TaskCreationOptions

.net - Elasticsearch 的 ID 使用什么格式?

C# - 线程 - 执行顺序

C# 将 Int 转换为两个十六进制字节?

asp.net - 在 ASP.NET 中,什么时候应该使用 Session.Clear() 而不是 Session.Abandon()?

javascript - 使用 javascript 将日期转换为 ccyymmdd