我正在尝试为没有单元测试的项目中的函数实现单元测试,并且此函数需要System.Web.Caching.Cache对象作为参数。我一直试图通过使用代码来创建这个对象,如...
System.Web.Caching.Cache cache = new System.Web.Caching.Cache();
cache.Add(...);
...然后将'cache'作为参数传递,但Add()函数导致NullReferenceException。到目前为止,我最好的猜测是我不能在单元测试中创建这个缓存对象,需要从HttpContext.Current.Cache中检索它,我显然在单元测试中无法访问它。
如何对需要System.Web.Caching.Cache对象作为参数的函数进行单元测试?
答案 0 :(得分:8)
当我遇到这类问题时(所讨论的类没有实现接口),我经常最终编写一个包含相关类的相关接口的包装器。然后我在我的代码中使用我的包装器。对于单元测试,我手工模拟包装器并将我自己的模拟对象插入其中。
当然,如果模拟框架有效,那么请使用它。我的经验是,所有模拟框架都存在各种.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);
...
答案 1 :(得分:2)
我认为你最好的选择是使用模拟对象(查看Rhino Mocks)。
答案 2 :(得分:1)
用于单元测试遗留代码的非常有用的工具是TypeMock Isolator。它将允许您完全绕过缓存对象,告诉它模拟该类以及您发现有问题的任何方法调用。与其他模拟框架不同,TypeMock使用反射拦截您告诉它为您模拟的方法调用,因此您不必处理繁琐的包装器。
TypeMock 是商业产品,但它有开源项目的免费版本。他们使用拥有一个单一用户许可的“社区”版本,但我不知道是否仍然提供此版本。
答案 3 :(得分:0)
var httpResponse = MockRepository.GenerateMock<HttpResponseBase>();
var cache = MockRepository.GenerateMock<HttpCachePolicyBase>();
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);