2010-03-22 7 views
30

Qualcuno potrebbe mostrarmi come procedere per creare un simulatore di Helper HTML con Moq?Come testare l'unità HtmlHelper con Moq?

Questo article ha un link ad un articolo sostenendo di descrivere questo, ma seguendo il link restituisce solo un errore runtime ASP.NET

[modifica] ho fatto una domanda più specifica relative allo stesso soggetto here, ma non ha ricevuto alcuna risposta. Ho pensato che fosse troppo specifico, quindi ho pensato che avrei potuto ottenere una risposta più generale a una domanda più generale e modificarla per soddisfare le mie esigenze.

Grazie

+0

Potete fornire parte del codice sotto esame? –

+0

@ Samuel, il codice pertinente è nella domanda a cui mi sono collegato nella mia modifica. – DaveDev

+0

In realtà non conosco una buona risposta (non ricordo davvero i dettagli di C#), ma l'ho svalutato nel tentativo di attirare l'attenzione su di esso =) –

risposta

10

Che cosa si può fare è questo:

HtmlHelper helper = null; 
helper.YourHelperMethod(); 

No bisogno di prendere in giro qualsiasi cosa Funziona brillante per me.

+28

Questo funziona solo se hai scritto un metodo di supporto che non usa l'helper, ovviamente. Se provi ad accedere a 'ViewContext',' RouteCollection', o qualsiasi altra cosa, questo non ti aiuta. –

+3

Questa non dovrebbe essere la risposta accettata. Risponde solo a un singolo scenario e non è il caso che devi usare Html Helper. Come ha detto @MattEnright, non ti sarà d'aiuto se hai bisogno di utilizzare il test Html Helper per generare Action Link, ad esempio. –

+1

Questa è ovviamente una risposta falsa -) – trailmax

41

Here 's un altro articolo che mostra come ottenere la stessa cosa:

public static HtmlHelper CreateHtmlHelper(ViewDataDictionary vd) 
{ 
    var mockViewContext = new Mock<ViewContext>(
    new ControllerContext(
     new Mock<HttpContextBase>().Object, 
     new RouteData(), 
     new Mock<ControllerBase>().Object), 
    new Mock<IView>().Object, 
    vd, 
    new TempDataDictionary()); 

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

    return new HtmlHelper(mockViewContext.Object, mockViewDataContainer.Object); 
} 
+5

Questa dovrebbe essere la risposta accettata. L'oggetto è effettivamente preso in giro qui. – SandRock

+2

Questo codice funziona solo per MVC4 e non per MVC5. –

+1

Ho apportato una modifica per MVC5. In attesa di revisione tra pari. – bradlis7

18

In MVC5, lo ViewContext ha un parametro di costruttore aggiuntivo per un TextWriter, quindi il codice di Thomas non funziona più. Ho aggiunto un TextWriter in memoria per aggirare questo problema:

public static HtmlHelper CreateHtmlHelper(ViewDataDictionary vd) 
{ 
    Mock<ViewContext> mockViewContext = new Mock<ViewContext>(
     new ControllerContext(
      new Mock<HttpContextBase>().Object, 
      new RouteData(), 
      new Mock<ControllerBase>().Object 
     ), 
     new Mock<IView>().Object, 
     vd, 
     new TempDataDictionary(), 
     new StreamWriter(new MemoryStream()) 
    ); 

    Mock<IViewDataContainer> mockDataContainer = new Mock<IViewDataContainer>(); 
    mockDataContainer.Setup(c => c.ViewData).Returns(vd); 

    return new HtmlHelper(mockViewContext.Object, mockDataContainer.Object); 
} 
+2

MVC4 richiede anche questa versione del codice – John

+0

Per utilizzare il ViewBag ho modificato la firma del metodo in 'public static HtmlHelper CreateHtmlHelper (ViewDataDictionary vd, object clientData)' e la riga di ritorno a 'var htmlHelper = new HtmlHelper (mockViewContext.Object, mockViewDataContainer .Oggetto); htmlHelper.ViewBag.Client = clientData; return htmlHelper; ' – LosManos

+0

È la risposta migliore fino ad ora ma non funzionerà se si ha un helper html che usa htmlHelper. Ad esempio, se si utilizza Html.action (...), viene generata una risposta nulla. –

1

Per testare helper usa e getta come BeginForm con accesso a ViewContext.Writer è possibile utilizzare questo:

public static HtmlHelper CreateHtmlHelper(ViewDataDictionary vd, Stream stream = null) 
{ 
    TextWriter textWriter = new StreamWriter(stream ?? new MemoryStream()); 
    Mock<ViewContext> mockViewContext = new Mock<ViewContext>(
     new ControllerContext(
      new Mock<HttpContextBase>().Object, 
      new RouteData(), 
      new Mock<ControllerBase>().Object 
     ), 
     new Mock<IView>().Object, 
     vd, 
     new TempDataDictionary(), 
     textWriter 
    ); 
    mockViewContext.Setup(vc => vc.Writer).Returns(textWriter); 

    Mock<IViewDataContainer> mockDataContainer = new Mock<IViewDataContainer>(); 
    mockDataContainer.Setup(c => c.ViewData).Returns(vd); 

    return new HtmlHelper(mockViewContext.Object, mockDataContainer.Object); 
} 
+0

ci deve essere qualcosa che manca . Ho ottenuto un 'System.NullReferenceException'. "Il riferimento non impostato su un'istanza di un oggetto". Qualche idea? – Blaise

+0

Probabilmente è necessario assicurarsi che 'CallBase' sia impostato su true sull'oggetto mock in modo che le proprietà siano impostate correttamente. Non dovresti aver bisogno di 'mockViewContext.Setup (vc => vc.Writer) .Returns (textWriter);' entrambi. –