2012-05-26 55 views
0

我需要设置在基本控制器的策略适用于所有控制器实例,象下面这样:初始化BaseController的领域使用的HttpContext,控制器设计

public class BaseController : Controller 
    { 

     private IPolicy Policy; 

     public BaseController() 
     { 
      this.Policy= new Policy(HttpContext); 
     } 
    } 

在策略类,我需要做的是这样的:

this.httpContextBase.User. 

问题:(更新

有什么更好的方法方面来设计BaseController使用HttpContext和Unit测试。

+1

那么,首先,它是理想的,如果你使用[全球](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)。 –

+0

不过,在单元测试中,这些actionmethod不会被调用。因此,Policy未初始化。 – Pingpong

回答

6

单元测试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()); 
} 
+0

在Initialize方法中,HttpContext不为null,但是在进行单元测试(BaseController的子类的实例化)时不会调用该方法。因此,访问策略字段时,“引用未设置为对象”的例外 – Pingpong

+0

@Pingpong,对不起,我的回答不完整。我忘了提供正确的设计方法。 –

+0

在依赖注入上,策略构造函数期望HttpContextBase参数,IoC容器是否能够注入它。我正在使用Unity IoC?感谢您的建议! – Pingpong