2008-11-07 13 views
23

Gibt es eine Möglichkeit, meine eigenen HtmlHelper (Einheit) zu testen? Für den Fall, dass ich eine benutzerdefinierte Steuerung (von HtmlHelper gerendert) haben möchte und Anforderungen an dieses Steuerelement habe, wie kann ich zuerst Tests schreiben und dann Code schreiben? Gibt es einen spezifischen (netten) Weg, das zu tun?Testen von HtmlHelpers in ASP.NET MVC

Ist es das wert?

Antwort

30

Das Hauptproblem ist, dass Sie den HtmlHelper verspotten müssen, weil Sie möglicherweise Methoden des Helfers verwenden, um Routen oder Werte zu erhalten oder das Ergebnis einer anderen Erweiterungsmethode zurückzugeben. Die HtmlHelper-Klasse hat ziemlich viele Eigenschaften und einige von ihnen ziemlich komplex wie der ViewContext oder der aktuelle Controller.

This post from Ben Hart, das erklärt, wie man einen solchen Schein mit Moq erstellt. Kann leicht in ein anderes Mock-Framework übersetzt werden.

Dies ist meine Rhino Mocks Version, die an die Änderungen im MVC Framework angepasst wurde. Es ist nicht vollständig getestet, aber es ist für mich arbeiten, aber nicht erwarten, ein perfektes Ergebnis:

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

leider die Post Fehler Blog aber die oben erklärt ganz gut, was Sie – MJJames

+1

tun müssen, Sieht aus wie sie die MV verändert haben C Framework leicht seit dem oben als ViewContext nimmt jetzt auch einen TextWriter –

+4

Dies ist sehr hilfreich, aber testing gegen MVC3 Ich musste dies durch Hinzufügen eines neuen Parameters zum mockViewContextConstructor (ich benutzte 'TextWriter.Null') und anstelle der mockViewDataContainer, ich musste ViewData explizit setzen (zB 'mockViewDataContainer.ViewData = viewData;') oder Rhino Mocks löst eine Exception aus. –

0

ich einen benutzerdefinierten Helfer zu schaffen, und das ist der Code, den ich bin mit dem httphelper mit Moq und ASP MVC zu verspotten 2. Ich übergebe auch als Parameter ein Mock der HttpRequestBase. Sie können das entfernen, wenn Sie es nicht brauchen

 
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

Wenn jemand sucht, wie HtmlHelper<T> zu erstellen (das ist, was ich war nach), hier ist eine Implementierung, die helfen könnte - mein Typ ist eine Klasse mit dem Namen Modell :

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

Oder eine allgemeinere Umsetzung:

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