2012-05-26 57 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