2011-11-29 12 views
26

Sono molto nuovo al test di unità anche se sono stato codificato per un tempo molto lungo. Voglio farne una parte del mio modo di sviluppo. Corro in blocchi su come testare le cose come una collezione. Generalmente ho il mio script jQuery che chiama i metodi lato ASP.Net Server per ottenere dati e popolare tabelle e simili. SembranoCome unit test JsonResult e Collections in MSTest

Get_*Noun*() 

che generalmente restituisce un JsonResult. Qualche idea su cosa e come testarli usando i test unitari usando MSTest?

risposta

49

Dovresti essere in grado di testarlo come qualsiasi altra cosa, purché tu possa estrarre i valori da JsonResult. Ecco un aiutante che lo farà per voi:

private T GetValueFromJsonResult<T>(JsonResult jsonResult, string propertyName) 
{ 
    var property = 
     jsonResult.Data.GetType().GetProperties() 
     .Where(p => string.Compare(p.Name, propertyName) == 0) 
     .FirstOrDefault(); 

    if (null == property) 
     throw new ArgumentException("propertyName not found", "propertyName"); 
    return (T)property.GetValue(jsonResult.Data, null); 
} 

Quindi chiamare il controller come al solito, e testare il risultato utilizzando tale aiuto.

var jsonResult = yourController.YourAction(params); 
bool testValue = GetValueFromJsonResult<bool>(jsonResult, "PropertyName"); 
Assert.IsFalse(testValue); 
+0

Anche se non è puramente adeguato per testare i risultati di un formato di trasporto, a volte quando si creano test attorno al codice legacy è temporaneamente inevitabile. Quindi questa è una buona soluzione. –

+6

@MarkFreedman "non è propriamente corretto per testare i risultati di un formato di trasporto" avete riferimenti o fonti per questo reclamo? –

+0

Bella risposta +1. –

19

(sto usando la sintassi NUnit, ma MSUnit non dovrebbe essere lontana)

Si potrebbe verificare la vostra JsonResult in questo modo:

var json = Get_JsonResult() 
dynamic data = json.Data; 
Assert.AreEqual("value", data.MyValue) 

Poi nel progetto che contiene il codice da verificare, modificare il file AssemblyInfo.cs per consentire all'assembly di test di accedere al tipo anonimo:

[assembly: InternalsVisibleTo("Tests")] 

In questo modo la dinamica può determinare il tipo di oggetto anonimo restituito dal valore json.Data;

+4

Giusto per chiarire: [assembly: InternalsVisibleTo ("TestProjectNamespace")] deve essere impostato nel progetto MVC AssemblyInfo.cs. –

+0

Anche per chiarire, la direttiva di assemblaggio va nel progetto che ha il codice in fase di test e non nel progetto di test stesso. – rboarman

+0

Non sono sicuro se questo è cambiato da quando questa domanda ha risposto, ma il compilatore si lamenterà che l'attributo 'InternalsVisibleTo' richiede un nome di assembly forte (firmato). Ciò complica le cose un bel po '. – karmasponge

3

This è il miglior blog che ho trovato su questo argomento.

Il mio preferito era il 4 ° approccio che utilizzava la dinamica. Si noti che è necessario assicurarsi che gli interni siano visibili per il progetto di test utilizzando [assembly:InternalsVisibleTo("TestProject")] che, in generale, è un'idea ragionevolmente buona.

[TestMethod]  
public void IndexTestWithDynamic()  
{  
    //arrange  
    HomeController controller = new HomeController();  

    //act  
    var result = controller.Index() as JsonResult;  

    //assert  
    dynamic data = result.Data; 

    Assert.AreEqual(3, data.Count);  
    Assert.IsTrue(data.Success);  
    Assert.AreEqual("Adam", data.People[0].Name);  
} 
+0

Perché dinamico? la proprietà .Data è di tipo oggetto che contiene ad esempio un elenco . Il risultato.Data può essere convertito in Elenco ... – Elisabeth

+2

@Elisa l'ipotesi sottostante in questa discussione è che il contenuto della proprietà .Data è un * tipo anonimo *. –

0

Here's a small extension per convertire facilmente un JSON ActionResult nell'oggetto che rappresenta.

using System.Web.Mvc; 

public static class WebExtensions 
{ 
    public static T ToJson<T>(this ActionResult actionResult) 
    { 
     var jsonResult = (JsonResult)actionResult; 

     return (T)jsonResult.Data; 
    } 
} 

Con questo, il vostro 'atto' nel test diventa più piccolo:

var myModel = myController.Action().ToJson<MyViewModel>(); 
+0

Ho fatto l'ultimo commento ... – pabloelustondo

0

Il mio suggerimento sarebbe quello di creare un modello per i dati restituiti e poi gettato il risultato in quel modello.In questo modo è possibile verificare:

  1. la struttura è corretto
  2. i dati all'interno del modello è corretto

    // Assert 
    var result = action 
        .AssertResultIs<JsonResult>(); 
    
    var model = (UIDSearchResults)result.Data; 
    Assert.IsTrue(model.IsValid); 
    Assert.AreEqual("ABC", model.UIDType); 
    Assert.IsNull(model.CodeID); 
    Assert.AreEqual(4, model.PossibleCodes.Count());