單元測試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