2008-11-07 4 views
23

(단위) 내 자신의 HtmlHelpers를 테스트 할 수있는 방법이 있습니까? HtmlHelper에 의해 렌더링 된 사용자 정의 컨트롤을 갖고 싶을 때, 컨트롤에 대한 requierements를 알고 있다면 어떻게하면 테스트를 먼저 작성한 다음 코드를 작성할 수 있습니까? 거기에 특정한 (멋진) 방법이 있습니까?ASP.NET MVC에서 HtmlHelpers 테스트

가치가 있습니까?

답변

30

주요 문제는 경로 또는 값을 가져 오거나 다른 확장 메서드의 결과를 반환하는 데 도우미 메서드를 사용할 수 있으므로 HtmlHelper를 조롱해야한다는 것입니다. HtmlHelper 클래스는 상당히 많은 속성을 가지고 있으며 그 중 일부는 ViewContext 또는 현재 컨트롤러와 같이 매우 복잡합니다.

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

+1

을해야 할 일을 설명하고 그들이 MV 변경 한 것 같은데 C 프레임 워크를 위의 약간 이후 ViewContext 이제 TextWriter 걸립니다. –

+4

이것은 매우 유용하지만 MVC3에 대한 테스트는 mockViewContextConstructor에 새 매개 변수를 추가하여 조정해야했습니다 ('TextWriter.Null' 사용) 대신 mockViewDataContainer, ViewData를 명시 적으로 설정해야했습니다 (예 :'mockViewDataContainer.ViewData = viewData;'). Rhino Mocks가 예외를 throw합니다. –

0

나는 사용자 지정 도우미를 만드는거야, 그리고 이것은 내가 MOQ 및 ASP MVC와 httphelper을 조롱하기 위해 사용하고 코드입니다 2. 또한 HttpRequestBase의 모의 매개 변수로 전달합니다. 내 타입이 클래스라는 이름의 모델이다 - 당신은 사람이 (즉, 내가 후 뭔지) HtmlHelper<T>을 만드는 방법을 찾고있는 경우

 
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

필요하지 않은 경우, 여기에 도움이 될 구현 것을 제거 할 수 있습니다 :

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); 
    }