我将如何模拟ControllerContext对象上的缓存对象进行单元测试?我已经尝试创建一个包装类,如下所示(因为缓存对象是一个密封类),没有运气。
var mockControllerContext = new Mock<ControllerContext>(); var mockhttpContext = new Mock<HttpContextBase>(); mockhttpContext.SetupGet(o => o.Cache).Returns( new CacheWrapper(mockControllerContext.Object.HttpContext.Cache)); mockControllerContext.SetupGet( o => o.HttpContext).Returns(mockhttpContext.Object); this.tennisMatchupController.ControllerContext = mockControllerContext.Object;
解决方法
编辑:我发现一个更简单的方法来做到这一点,至少在使用空缓存测试时。使用HttpRunTime.Cache作为HttpContext的Cache属性的期望值的返回值。对于更高级的场景,使用包装和嘲笑可能仍然是更好的处理方式 – 例如,如果您需要从缓存中测试异常。
var httpContext = MockRepository.GenerateMock<HttpContextBase>(); httpContext.Expect( h => h.Cache ).Return( HttpRunTime.Cache ).Repeat.Any()
原版的:
包装类是要走的路,但我认为你在错误的地方应用它。我会给我的控制器一个CacheWrapper属性,然后创建一个构造函数,允许我传递一个可以设置此属性的CacheWrapper实例。默认情况下,控制器使用HttpContext.Current.Cache创建一个CacheWrapper。在测试代码中,构造一个模拟CacheWrapper以传入控制器的构造函数。这样你就不需要创建一个模拟缓存对象了 – 这很难,因为它是一个密封类。
或者,您可以实例化一个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(); }