【发布时间】:2014-12-04 04:37:07
【问题描述】:
以下测试间歇性地失败。它在 MemoryCache 中缓存一个具有绝对过期时间的项目,以及一个应该在删除项目之前调用的更新回调。然而,有时回调会在测试完成之前被调用,有时根本不会。
如果缓冲时间足够大,它将始终至少被调用一次。但这不符合我的目的,因为我要求缓存总是在数据过期之前尝试更新数据。
现在在我的真实世界场景中,我不会有 10 秒的过期时间和粒度,但我仍然担心这个测试间歇性地失败。
有人知道为什么会这样吗?
注意:60 秒到期和 5 秒缓冲也会间歇性失败。
using System;
using System.Runtime.Caching;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class MemoryCacheTest
{
private const double ExpiryInSeconds = 10;
private const double ExpiryBufferInSeconds = 5;
private readonly object updateItemCounterLock = new object();
private int updateItemCounter = 0;
[TestMethod]
public async Task MemoryCacheUpdateTest()
{
// Set item in cache with absolute expiration defined above
MemoryCache cache = MemoryCache.Default;
CacheItem cacheItem = new CacheItem("key", "value");
CacheItemPolicy cacheItemPolicy = new CacheItemPolicy
{
AbsoluteExpiration = DateTimeOffset.Now + TimeSpan.FromSeconds(ExpiryInSeconds),
UpdateCallback = new CacheEntryUpdateCallback(this.UpdateItem)
};
cache.Set(cacheItem, cacheItemPolicy);
// Delay for absolute expiration time + buffer
await Task.Delay(TimeSpan.FromSeconds(ExpiryInSeconds) + TimeSpan.FromSeconds(ExpiryBufferInSeconds));
// Test that the update callback was invoked once
Assert.AreEqual(1, updateItemCounter);
}
// Incrememnts the updateItemCounter
private void UpdateItem(CacheEntryUpdateArguments args)
{
lock (updateItemCounterLock)
{
updateItemCounter++;
}
}
}
【问题讨论】:
-
如果您注意到,AbsoluteExpiration 值表示该项目将被驱逐的时间量。这意味着它是保持有效的最短时间,而不是(具有讽刺意味的)绝对时间。这里的绝对是指它不是一个滑动的时间限制......并不是说它会在那个确切的时刻被驱逐。基本上,该项目可以在到期后的任何时间被驱逐,这可能是几秒钟,甚至几分钟后。我的测试表明,到期时间可能会在到期时间后 0 到 30 秒之间的任何时间发生,但可能会更长。
-
这篇文章似乎表明内部实现有某种硬连线的 20 秒计时器:stackoverflow.com/questions/12630168/… 不确定这是否正确,但它肯定与我在我的测试结果。
标签: c# asp.net unit-testing caching memorycache