2009-04-05 6 views
25

Sto facendo alcuni semplici test delle unità MS sul mio standard, niente controller speciale.L'unità testando il metodo del mio controller genera un ViewName vuoto?

Quando controllo il proprietario dall'oggetto ViewResult restituito, è "" (vuoto).

Ho l'impressione che il ViewName sia implicito dal nome dello View (come suggested by this MS article sul test del controller ASP.NET MVC).

BTW, quando eseguo il test di ViewData, è tutto lì e corretto.

Ecco il codice che ho ...

public ActionResult Index(int? page, string tag) 
{ 
    if (page == null || page <= 0) 
    { 
     page = 1; 
    } 

    var viewData = new IndexViewData 
         { 
         ... my property setters, etc ... 
         }; 
    return View(viewData); 
} 

[TestMethod] 
public void Index_Action_Should_Return_Index_View_For_Default_HomePage() 
{ 
    // Arrange. 
    var controller = PostController; // Wrapper, cause I use D.I. 

    // Act. 
    ViewResult viewResult = controller.Index(null, null) as ViewResult; 

    // Assert. 
    Assert.IsNotNull(viewResult); 
    Assert.AreEqual("Index", viewResult.ViewName); // This is false/fails. 

    var indexViewData = viewResult.ViewData.Model as IndexViewData; 
    Assert.IsNotNull(indexViewData); // This is true. 
} 

risposta

27

La ViewName è presente solo quando si imposta nel ViewResult. Se il nome della vista corrisponde al nome del controller, faremo in modo che il ViewName sia nullo o vuoto, in quanto sarebbe (IMO) il comportamento corretto poiché non si desidera impostare un nome sulla vista. Controllo solo che ViewName sia impostato quando intendo che la vista da restituire non corrisponde all'azione, ad esempio quando si restituisce la vista "Errore", ad esempio.

EDIT: Quanto segue è la fonte per ExecuteResult in ViewResultBase.cs (da RC1, non ho la sorgente per RTW sul mio Macintosh). Come puoi vedere controlla se il ViewName è stato impostato direttamente e in caso contrario, lo estrae dall'azione nei dati di rotta del contesto del controller. Questo accade solo in ExecuteResult, che viene richiamato dopo che l'azione del controller è stata completata.

public override void ExecuteResult(ControllerContext context) { 
     if (context == null) { 
      throw new ArgumentNullException("context"); 
     } 
     if (String.IsNullOrEmpty(ViewName)) { 
      ViewName = context.RouteData.GetRequiredString("action"); 
     } 

     ViewEngineResult result = null; 

     if (View == null) { 
      result = FindView(context); 
      View = result.View; 
     } 

     ViewContext viewContext = new ViewContext(context, View, ViewData, TempData); 
     View.Render(viewContext, context.HttpContext.Response.Output); 

     if (result != null) { 
      result.ViewEngine.ReleaseView(context, View); 
     } 
    } 
+0

Heya. Hmm. non capisco quello che stai dicendo. "Il ViewName è presente solo quando lo si imposta in ViewResult". Pensavo che il framework auto lo imposta? Stai dicendo che non è impostato automaticamente? –

+0

No. Per quanto posso dire che il ViewName è nullo a meno che non lo si imposta in modo specifico. Credo che se è nullo o vuoto, tira il nome della vista dal nome dell'azione. – tvanfosson

+0

>> Credo che se è nullo o vuoto, tira il nome della vista dal nome dell'azione. << Hmm .. quindi questo significa che non dovrebbe essere nullo, giusto? –

0

Il nome di vista viene impostato automaticamente dal framework. Ma quando eseguiamo un test unitario, cortocircuiamo il framework e non è rimasto nulla per impostare il nome.

Quindi le nostre azioni devono impostare esplicitamente il nome di vista quando eseguiamo il test dell'unità. Potremmo anche verificare se sono vuoti o nulli se vogliamo davvero appoggiarci alla convenzione.

2

Personalmente ho trovato le strutture di test fornite da MVC2 per essere un po 'goffe. Immagino che esista già qualcosa di meglio, ma alla fine ho creato una semplice classe per testare le azioni. Ho modellato l'interfaccia (l'implementazione è un'altra storia) su una classe fornita dall'eccellente open source Java MVC framework Stripes chiamato MockRoundTrip.

Ecco il metodo utilizzato per ottenere la pagina di destinazione dell'azione durante il test delle azioni, denominata getTripDestination(). Si restituisce il risultato corretto indipendentemente dal fatto che il ViewName è impostata in modo esplicito o meno

//Get the destination page of the request, using Runtime execution pattern of MVC, namely 
    //if no ViewName is explicitly set in controller, ViewResult will have an empty ViewName 
    //Instead, current action name will be used in its place 
    public string getTripDestination() 
    { 
     RouteData routeData = getRouteData(); 
     ViewResult viewResult = (result is ViewResult) ? (ViewResult)result : null; 
     string tripDestination = (viewResult != null) ? viewResult.ViewName : ""; 

     return (tripDestination != "") ? tripDestination : (String)routeData.Values["action"]; 
    } 

    private RouteData getRouteData() 
    { 
     HttpContextBase context = controller.ControllerContext.RequestContext.HttpContext; 
     return RouteTable.Routes.GetRouteData(context); 
    } 
0

I documentation for Controller.View() stati:

Questo overload del metodo della classe View restituisce un oggetto ViewResult che ha un ViewName vuoto proprietà. Se si stanno scrivendo unit test per le azioni del controllore , prendere in considerazione la proprietà ViewName vuota per i test di unità che non accettano un nome di visualizzazione stringa.

In fase di esecuzione, se la proprietà ViewName è vuota, il nome corrente di azione viene utilizzato al posto della proprietà ViewName.

Quindi, quando ci si aspetta una vista con lo stesso nome dell'azione corrente, è sufficiente verificare che si tratti di una stringa vuota.

In alternativa, il metodo Controller.View (String) imposterà il ViewName.

Problemi correlati