编辑:我发现一种更简单的方法来做这件事,至少在测试空缓存时是这样的。使用HttpRunTime.Cache作为HttpContext的Cache属性的期望返回值。对于更高级的场景,使用包装器和模拟可能仍然是处理它的更好方法--例如,如果您需要测试来自缓存的异常。
var httpContext = MockRepository.GenerateMock<HttpContextBase>();
httpContext.Expect( h => h.Cache ).Return( HttpRunTime.Cache ).Repeat.Any()
Translated:
包装类是解决问题的方式,但我认为你把它应用在了错误的地方。我会给我的控制器一个CacheWrapper属性,并创建一个构造函数,允许我传递一个CacheWrapper实例,并将其设置为该属性。默认情况下,控制器使用HttpContext.Current.Cache创建CacheWrapper。在测试代码中,构造一个模拟CacheWrapper并将其传递到控制器的构造函数中。这样你就不需要创建一个模拟的Cache对象——这很难,因为它是一个密封类。
另外,你也可以只实例化一个Cache类的实例并返回它,因为它有一个公共的构造函数。然而,使用模拟有一个优点,你可以通过预期验证Cache是否被使用,所以我可能会选择使用包装类。
public class CacheWrapper
{
private Cache Cache { get; set; }
public CacheWrapper()
{
this.Cache = HttpContext.Current.Cache;
}
public virtual Object Add( string key,
Object value,
CacheDependency dependencies,
DateTime absoluteExpiration,
TimeSpan slidingExpiration,
CacheItemPriority priority,
CacheItemRemovedCallback onRemoveCallback )
{
this.Cache.Add( key,
value,
dependencies,
absoluteExpiration,
slidingExpiration,
priority,
onRemoveCallback );
}
...wrap other methods...
}
public class BaseController : Controller
{
private CacheWrapper { get; set; }
public BaseController() : this(null) { }
public BaseController( CacheWrapper cache )
{
this.CacheWrapper = cache ?? new CacheWrapper();
}
}
[TestMethod]
public void CacheTest()
{
var wrapper = MockRepository.GenerateMock<CacheWrapper>();
wrapper.Expect( o => o.Add( ... ) ).Return( ... );
var controller = new BaseController( wrapper );
var result = controller.MyAction() as ViewResult;
Assert.AreEqual( ... );
wrapper.VerifyAllExpectations();
}