我有以下测试用例:
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)
我复制了你的代码,测试通过了我的机器。
但是你应该重新考虑你的测试,因为你正在尝试测试只是包装ObjectCache的MyCache。您不需要测试缓存过期(因为它是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
(其中time是{的实例注入的{ {1}})在您的代码中 - 真正的实现将返回ITime
并且在您的单元测试中您可以用固定时间模拟它(然后声明过期是固定时间加上TEST_EXPIRATION)