2014-12-04 69 views
0

以下测试会间歇性失败。它在MemoryCache中缓存具有绝对过期时间的项目,以及在项目被移除之前应该调用的更新回调。但是有时在测试结束之前调用回调,有时甚至根本没有回调。使用MemoryCache进行测试UpdateCallback

有了足够大的缓冲时间,它总是会被调用至少一次。但是这并不符合我的目的,因为我要求缓存总是在数据过期之前尝试更新数据。

现在在我的现实世界中的场景,我不会有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++; 
     } 
    } 
} 
+0

如果您注意到,AbsoluteExpiration值表示物品将被驱逐的时间量。这意味着这是它保持有效的最短时间,没有(具有讽刺意味的)绝对时间。这里的绝对是指这个事实,它不是一个滑动时间限制......并不是它会在那个时刻被驱逐。基本上,该物品可以在到期后的任何时间被驱逐,这可能是几秒钟,甚至几分钟后。我的测试表明,到期时间可以在0到30秒后的任何时间发生,但可能会更长。 – 2014-12-04 06:48:28

+1

这篇文章似乎表明,内部实现具有某种硬连线20秒计时器:http://stackoverflow.com/questions/12630168/memorycache-absoluteexpiration-acting-strange不知道这是否正确,但它肯定与我在测试结果中看到的相符。 – 2014-12-04 07:08:54

回答

0

因为这个问题没有解决方案,所以我抽取了我需要的MemoryCache方法到一个接口中并进行了测试。此时,测试变得无效,因为我只是测试了我自己的接口实现。

0

我想调用新的CacheEntryUpdateCallback是多余的。你可以调用: UpdateCallback = new CacheEntryUpdateCallback(this.UpdateItem)改为