单元测试HttpContext的正确方法是什么?
绝对没有办法。当此上下文仍未初始化时,您正在使用控制器的构造函数中的HttpContext
。不仅这个代码不能被测试,而且当你运行应用程序时,它也会与NRE一起崩溃。你不应该在控制器的构造函数中使用任何HttpContext相关的东西。
一种可能性是重构你的代码并执行这个Initialize方法中:
public class BaseController : Controller
{
private IPolicy Policy;
protected override void Initialize(RequestContext requestContext)
{
base.Initialize(requestContext);
this.Policy = new Policy(HttpContext);
}
}
这是说,这不是我推荐的方法。我建议你使用依赖注入而不是许多人认为的反模式服务位置。
所以:
public abstract class BaseController : Controller
{
protected IPolicy Policy { get; private set; }
protected BaseController(IPolicy policy)
{
Policy = policy;
}
}
现在,所有剩下的就是配置自己喜欢的依赖注入框架,以正确的实例注入到构造函数。例如与Ninject.Mvc3这是用一行代码实现的:
kernel.Bind<IPolicy>().To<Policy>();
现在你可以感觉比免费更在你的单元测试嘲笑这个IPolicy甚至不关心任何的HttpContext。
例如,让我们假设你有你想要的单元测试以下控制器:
public class FooController : BaseController
{
public FooController(IPolicy policy): base(policy)
{ }
[Authorize]
public ActionResult Index()
{
Policy.DoSomething();
return View();
}
}
现在,所有你需要做的就是拿起你最喜欢的模拟框架(犀牛嘲笑我的情况)并做嘲弄:
[TestMethod]
public void Index_Action_Should_DoSomething_With_The_Policy()
{
// arrange
var policyStub = MockRepository.GenerateStub<IPolicy>();
var sut = new FooController(policyStub);
// act
var actual = sut.Index();
// assert
Assert.IsInstanceOfType(actual, typeof(ViewResult));
policyStub.AssertWasCalled(x => x.DoSomething());
}
那么,首先,它是理想的,如果你使用[全球](http://weblogs.asp.net/gunnarpeipman/archive/2010/08/15/asp-net- mvc-3-global-action-filters.aspx)[action filters](http://msdn.microsoft.com/en-us/library/gg416513(v = vs.98).aspx)而不是[通用基础类](HTTP:// stackov erflow.com/questions/6119206/what-are-good-candidates-for-base-controller-class-in-asp-net-mvc)。 –
不过,在单元测试中,这些actionmethod不会被调用。因此,Policy未初始化。 – Pingpong