2016-07-21 2 views
0

У меня есть следующий тестовый случай:Тест неудачу с помощью Moq и таймер

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

Я скопировал ваш код и проходит тест на моей машине.

Однако вы должны, вероятно, пересмотреть свой тест, поскольку вы пытаетесь проверить MyCache, который просто обертывает ObjectCache. Вам не нужно проверять срок действия кеша (поскольку это часть ObjectCache и должна быть частью его модульных тестов), но только тот MyCache правильно делегирует операции Get и Set 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)

Смежные вопросы