在unit testing中创建System.Web.Caching.Cache对象

我正在尝试为没有unit testing的项目中的函数实现unit testing,并且此函数需要System.Web.Caching.Cache对象作为参数。 我一直试图通过使用诸如……之类的代码来创建这个对象。

System.Web.Caching.Cache cache = new System.Web.Caching.Cache(); cache.Add(...); 

…然后将’cache’作为参数传递,但Add()函数导致NullReferenceException。 到目前为止,我最好的猜测是我不能在unit testing中创建这个缓存​​对象,需要从HttpContext.Current.Cache中检索它,我在unit testing中显然无法访问它。

如何对需要System.Web.Caching.Cache对象作为参数的函数进行unit testing?

当我遇到这种问题时(所讨论的类没有实现接口),我经常最终编写一个包含相关类的相关接口的包装器。 然后我在我的代码中使用我的包装器。 对于unit testing,我手工模拟包装器并将我自己的模拟对象插入其中。

当然,如果模拟框架有效,那么请使用它。 我的经验是,所有模拟框架都存在各种.NET类的问题。

 public interface ICacheWrapper { ...methods to support } public class CacheWrapper : ICacheWrapper { private System.Web.Caching.Cache cache; public CacheWrapper( System.Web.Caching.Cache cache ) { this.cache = cache; } ... implement methods using cache ... } public class MockCacheWrapper : ICacheWrapper { private MockCache cache; public MockCacheWrapper( MockCache cache ) { this.cache = cache; } ... implement methods using mock cache... } public class MockCache { ... implement ways to set mock values and retrieve them... } [Test] public void CachingTest() { ... set up omitted... ICacheWrapper wrapper = new MockCacheWrapper( new MockCache() ); CacheManager manager = new CacheManager( wrapper ); manager.Insert(item,value); Assert.AreEqual( value, manager[item] ); } 

真正的代码

 ... CacheManager manager = new CacheManager( new CacheWrapper( HttpContext.Current.Cache )); manager.Add(item,value); ... 

我认为你最好的选择是使用模拟对象(看看Rhino Mocks)。

用于unit testing遗留代码的非常有用的工具是TypeMock Isolator 。 它将允许您完全绕过缓存对象,告诉它模拟该类以及您发现有问题的任何方法调用。 与其他模拟框架不同,TypeMock使用reflection拦截您告诉它为您模​​拟的方法调用,因此您不必处理繁琐的包装器。

TypeMock 一个商业产品,但它有开源项目的免费版本。 他们曾经有一个“社区”版本,这是一个单用户许可证,但我不知道是否仍然提供。

 var httpResponse = MockRepository.GenerateMock(); var cache = MockRepository.GenerateMock(); cache.Stub(x => x.SetOmitVaryStar(true)); httpResponse.Stub(x => x.Cache).Return(cache); httpContext.Stub(x => x.Response).Return(httpResponse); httpContext.Response.Stub(x => x.Cache).Return(cache);