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

C# 如何在集成测试之间刷新IAppCache,c#,asp.net,.net,unit-testing,integration-testing,C#,Asp.net,.net,Unit Testing,Integration Testing,我正在ASP.NET中运行与xUnit的集成测试,其中一个测试确保多次查询数据只会导致对服务器的一次查询。如果我单独运行这个测试,那么它可以工作。如果我运行所有的测试,那么服务器将被该测试查询0次而不是1次。这表示由于其他测试,结果已在缓存中 如何确保IAppCache在测试开始时为空?我正在使用LazyCache实现 我的猜测是,每个测试都会重新创建类实例,但静态数据是共享的;缓存是静态的。我在缓存上看不到任何“flush”方法。正如我的评论中提到的,LazyCache afaik没有清除操作

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

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


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

正如我的评论中提到的,LazyCache afaik没有清除操作或任何本机的方法来对缓存进行核爆。不过,我认为有几个选择供你选择

  • 在每次测试之前/之后,使用remove实现一种删除缓存项的方法
  • 为测试提供不同的LazyCache缓存提供程序,该提供程序不会在测试之间持久化缓存
  • 深入研究LazyCache,获取底层缓存提供程序,看看是否有任何方法可以清除缓存项
我会选择1或3个。从测试的角度来看,1意味着您需要了解所测试内容的内部结构。如果是我,我有点懒,可能会写几行代码来破坏缓存

默认情况下,LazyCache用作缓存提供程序。MemoryCache也没有显式的清除操作,但当压缩百分比设置为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";
    }
}
void Main()
{
IAppCache cache=new CachingService();
WriteLine(cache.GetOrAdd(“Foo”,()=>Foo.NewFoo,DateTimeOffset.Now.AddHours(1.0));
var cacheProvider=cache.cacheProvider;
var memoryCache=(memoryCache)cacheProvider.GetType().GetField(“缓存”,BindingFlags.Instance | BindingFlags.NonPublic).GetValue(cacheProvider);
memoryCache.Compact(1.0);
Console.WriteLine(cache.Get(“Foo”);
}
公开课Foo
{
公共静态Foo NewFoo
{
得到
{
Console.WriteLine(“工厂调用”);
返回新的Foo();
}
}
公共重写字符串ToString()
{
返回“我是一个foo”;
}
}
每次运行都会产生以下结果:

如果删除压缩调用,我们将得到以下结果:


因此,这表明Compact(1.0)即使到期日为+1小时,也会对缓存项进行核爆。

LazyCache under the cover使用MS memorycache。没有明确的规定或规定,以获得所有的钥匙。选项取决于您如何进行集成测试;您是否需要真正的缓存服务,或者是否可以注入一个mock;如果您需要真实的东西,您可以实现一个过程来清除测试之间的缓存。听起来您可能正在测试LazyCache本身,如果可能的话,请避免这样做。对于这个特定的测试,我确实在测试LazyCache的代码在并发请求的情况下是否按预期执行。清除缓存的过程。。。这正是我要问的。哇,我正在考虑对那个特定的测试进行注释,但在运行那个特定的测试之前,用这种方式对缓存进行nuking处理效果很好。我正在将它转换为CachingService.Nuke()扩展方法。听起来比清晰好多了!