2008-11-07 62 views
23

有什麼辦法可以(單元)測試我自己的HtmlHelpers嗎?如果我想要自定義控件(由HtmlHelper呈現),並且我知道該控件的必要條件,那麼我怎樣才能先編寫測試 - 然後編寫代碼?有沒有特定的(很好的)方法來做到這一點?在ASP.NET MVC中測試HtmlHelpers

值得嗎?

回答

30

主要問題是您必須模擬HtmlHelper,因爲您可能正在使用幫助器的方法來獲取路由或值或返回另一個擴展方法的結果。 HtmlHelper類具有相當多的屬性,其中一些非常複雜,比如ViewContext或當前的Controller。

This post from Ben Hart解釋瞭如何用Moq創建這樣的模擬。可以很容易地轉換到另一個模擬框架。

這是我的Rhino Mocks版本適應MVC框架的變化。這不是全面的測試,但它爲我工作,但不要指望完美的結果:

public static HtmlHelper CreateHtmlHelper(ViewDataDictionary viewData) 
    { 
     var mocks = new MockRepository(); 

     var cc = mocks.DynamicMock<ControllerContext>(
      mocks.DynamicMock<HttpContextBase>(), 
      new RouteData(), 
      mocks.DynamicMock<ControllerBase>()); 

     var mockViewContext = mocks.DynamicMock<ViewContext>(
      cc, 
      mocks.DynamicMock<IView>(), 
      viewData, 
      new TempDataDictionary()); 

     var mockViewDataContainer = mocks.DynamicMock<IViewDataContainer>(); 

     mockViewDataContainer.Expect(v => v.ViewData).Return(viewData); 

     return new HtmlHelper(mockViewContext, mockViewDataContainer); 
    } 
+2

可悲的博客文章錯誤,但上述解釋得很好,你需要做什麼 – MJJames 2010-08-07 18:43:20

0

我創建一個自定義的幫手,這是我用來嘲笑與起訂量和ASP MVC的httphelper代碼2.我也作爲參數傳遞HttpRequestBase的模擬。您可以刪除,如果你不需要它

 
public static HtmlHelper CreateHtmlHelper(ViewDataDictionary viewData, Mock requestMock) 
     { 
      var contextBaseMock = new Mock(); 
      contextBaseMock.SetupGet(cb => cb.Request).Returns(requestMock.Object); 

      var cc = new ControllerContext(contextBaseMock.Object, 
              new RouteData(), 
              new Mock().Object); 
      var vctx = new ViewContext(
       cc, 
       new Mock().Object, 
       viewData, 
       new TempDataDictionary(), 
       new HtmlTextWriter(new StreamWriter(new MemoryStream()))); 

      var mockViewDataContainer = new Mock(); 

      mockViewDataContainer.SetupGet(v => v.ViewData).Returns(viewData); 

      return new HtmlHelper(vctx, mockViewDataContainer.Object); 
     } 
9

如果有人正在尋找如何創建HtmlHelper<T>(這就是我)後,這裏是一個可能有助於實現 - 我喜歡的類型是一類名爲型號:

public static HtmlHelper<Model> CreateHtmlHelper() 
{ 
    ViewDataDictionary vd = new ViewDataDictionary(new Model()); 

    var controllerContext = new ControllerContext(new Mock<HttpContextBase>().Object, 
                new RouteData(), 
                new Mock<ControllerBase>().Object); 

    var viewContext = new ViewContext(controllerContext, new Mock<IView>().Object, vd, new TempDataDictionary(), new Mock<TextWriter>().Object); 

    var mockViewDataContainer = new Mock<IViewDataContainer>(); 
    mockViewDataContainer.Setup(v => v.ViewData).Returns(vd); 

    return new HtmlHelper<Model>(viewContext, mockViewDataContainer.Object); 
} 

或者一個更通用的實現:

public HtmlHelper<T> CreateHtmlHelper<T>() where T : new() 
    { 
     var vd = new ViewDataDictionary(new T()); 

     var controllerContext = new ControllerContext(new Mock<HttpContextBase>().Object, 
                 new RouteData(), 
                 new Mock<ControllerBase>().Object); 

     var viewContext = new ViewContext(controllerContext, new Mock<IView>().Object, vd, new TempDataDictionary(), new Mock<TextWriter>().Object); 

     var mockViewDataContainer = new Mock<IViewDataContainer>(); 
     mockViewDataContainer.Setup(v => v.ViewData).Returns(vd); 

     return new HtmlHelper<T>(viewContext, mockViewDataContainer.Object); 
    }