2016-07-21 33 views
0

失敗,我有以下測試案例:測試使用起訂量和定時器

private static readonlystring TEST_KEY = "SomeKey"; 
private static readonly object TEST_VALUE = 2; 
private static readonlyTimeSpan TEST_EXPIRATION = TimeSpan.FromSeconds(2); 

[TestMethod] 
public void SetMethodStoresValueForCorrectTime() 
{ 
    Mock<ObjectCache> mock = new Mock<ObjectCache>(); 

    // Setup mock's Set method 
    mock.Setup(m => m.Set(TEST_KEY, TEST_VALUE, It.IsAny<DateTimeOffset>(), It.IsAny<string>())) 
    .Callback(() => mock.Setup(m => m.Get(TEST_KEY, It.IsAny<string>())).Returns(TEST_VALUE)); 

    MyCache<object> instance = new MyCache<object>(mock.Object); 

    // Add value to mocked cache 
    instance.Set(TEST_KEY, TEST_VALUE, TEST_EXPIRATION); 
    Assert.AreEqual(TEST_VALUE, instance.Get(TEST_KEY)); 

    // Configure a timer for item's expiration (Make mock's Get method return null) 
    Timer timer = new Timer(_ => mock.Setup(m => m.Get(TEST_KEY, It.IsAny<string>())).Returns(null), null, TEST_EXPIRATION.Milliseconds, -1); 

    // Wait for TimerCallback to trigger 
    Thread.Sleep(TEST_EXPIRATION.Add(TimeSpan.FromSeconds(1))); 
    Assert.IsNull(instance.Get(TEST_KEY)); // <-- Failing here 

    timer.Dispose(); 
} 

,這裏是MyCache<T>(它的相關部分):

public class MyCache<TSource> : ICache<TSource> 
{ 
    private ObjectCache _innerCache; 

    public MyCache(System.Runtime.Caching.ObjectCache innerCache) 
    { 
     _innerCache = innerCache; 
    } 

    // ... 

    public TSource Get(string key) 
    { 
     if (key == null) throw new ArgumentNullException("key"); 
     object value = _innerCache.Get(key); 
     return value != null ? (TSource)value : default(TSource); 
    } 

    public void Set(string key, TSource value, TimeSpan expiration) 
    { 
     if (key == null) throw new ArgumentNullException("key"); 
     _innerCache.Set(key, value, DateTimeOffset.UtcNow.Add(expiration)); 
    } 
} 

爲什麼測試失敗? 它未能在最後斷言:

Assert.IsNull失敗。

我在這裏做錯了什麼?

+0

爲什麼你要創建一個計時器而不使用它(除了處理它)? –

+0

@JeroenHeier它應該在'TEST_EXPIRATION.Milliseconds'毫秒後自動啓動 –

回答

0

我複製了你的代碼,測試通過了我的機器。

但是,您應該重新考慮您的測試,因爲您正在測試只是簡單包裝ObjectCache的MyCache。您不需要測試緩存過期(因爲這是ObjectCache的一部分,應該是其單元測試的一部分),但僅需MyCache將獲取和設置操作正確委派給ObjectCache。例如:

[TestMethod] 
    public void SetMethodStoresValueInInnerCache() 
    { 
     Mock<ObjectCache> mock = new Mock<ObjectCache>(); 

     MyCache<object> instance = new MyCache<object>(mock.Object); 

     // Add value to mocked cache 
     instance.Set(TEST_KEY, TEST_VALUE, TEST_EXPIRATION); 

     mock.Verify(x => x.Set(TEST_KEY, TEST_VALUE, It.IsAny<DateTimeOffset>(), It.IsAny<string>()), Times.Once); 
    } 

您可以獲得Get的等價物。
如果你想測試MyCache正確設置期滿(代碼DateTimeOffset.UtcNow.Add(expiration)),那麼你可以創建一個接口一樣ITime和使用time.UtcNow(其中時間是ITime注入實例)在你的代碼 - 真正的實現將返回DateTime.UtcNow並且在你的單元測試中,你可以用一個固定的時間來嘲弄它(然後斷言到期時間是固定時間加上TEST_EXPIRATION)