Pin*_*ong 0 architecture asp.net-mvc unit-testing design-patterns
我需要在基本控制器中设置一个适用于所有控制器实例的策略,如下所示:
public class BaseController : Controller
{
private IPolicy Policy;
public BaseController()
{
this.Policy= new Policy(HttpContext);
}
}
Run Code Online (Sandbox Code Playgroud)
在Policy类中,我需要执行以下操作:
this.httpContextBase.User.
Run Code Online (Sandbox Code Playgroud)
问题:( 更新)
在使用HttpContext和Unit测试方面设计BaseController的更好方法是什么.
单元测试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);
}
}
Run Code Online (Sandbox Code Playgroud)
这就是说,这不是我推荐的方法.我建议您使用依赖注入而不是服务位置,这被许多人视为反模式.
所以:
public abstract class BaseController : Controller
{
protected IPolicy Policy { get; private set; }
protected BaseController(IPolicy policy)
{
Policy = policy;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,剩下的就是配置您喜欢的依赖注入框架,将正确的实例注入构造函数中.例如,使用Ninject.Mvc3,只需一行代码即可实现:
kernel.Bind<IPolicy>().To<Policy>();
Run Code Online (Sandbox Code Playgroud)
现在你可以在单元测试中自由地模仿这个IPolicy而不用关心任何HttpContext.
例如,假设您有以下要进行单元测试的控制器:
public class FooController : BaseController
{
public FooController(IPolicy policy): base(policy)
{ }
[Authorize]
public ActionResult Index()
{
Policy.DoSomething();
return View();
}
}
Run Code Online (Sandbox Code Playgroud)
现在,您需要做的就是选择您喜欢的模拟框架(在我的情况下是Rhino Mocks)并进行模拟:
[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());
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1285 次 |
最近记录: |