我对测试和MVC相对较新,今天遇到了一个棘手的问题。我正在尝试测试一个依赖于HttpContext.Current.Cache的动作方法,并想知道实现“低耦合”以便于测试的最佳实践。这是我到目前为止所得到的......
public class CacheHandler : ICacheHandler
{
public IList<Section3ListItem> StateList
{
get { return (List<Section3ListItem>)HttpContext.Current.Cache["StateList"]; }
set { HttpContext.Current.Cache["StateList"] = value; }
}
...
然后我就这样访问了......我正在使用Castle作为我的IoC。
public class ProfileController : ControllerBase
{
private readonly ISection3Repository _repository;
private readonly ICacheHandler _cache;
public ProfileController(ISection3Repository repository, ICacheHandler cacheHandler)
{
_repository = repository;
_cache = cacheHandler;
}
[UserIdFilter]
public ActionResult PersonalInfo(Guid userId)
{
if (_cache.StateList == null)
_cache.StateList = _repository.GetLookupValues((int)ELookupKey.States).ToList();
...
然后在我的单元测试中,我可以模拟ICacheHandler。
这会被视为“最佳做法”,是否有人对其他方法有任何建议?
答案 0 :(得分:2)
推荐的方法是存根HttpContextBase。其文件说明
当你进行单元测试时,你 通常使用派生类 实现定制的成员 满足场景的行为 你正在测试。
这主要适用于TypeMock here。
var httpContext = MockRepository.GenerateStub<HttpContextBase>();
httpContext.Stub(x=>x.Cache).Return(yourFakeCacheHere);
var controllerContext = new ControllerContext(httpContext, ....);
var controller = new HomeController();
controller.ControllerContext = controllerContext;
答案 1 :(得分:1)
您隐藏了一个特定的,难以测试的API (HttpContext.Current),并且使用构造函数注入将依赖项注入到使用者中。这或多或少是教科书DI (我会在构造函数中添加Guard子句)。
如果在Visual Studio中创建一个新的ASP.NET MVC项目,您将看到在AccountController.cs文件中,正在执行一项非常类似的操作来隐藏MembershipProvider。