Condividi tramite


Creazione di unit test per le applicazioni ASP.NET MVC (C#)

di Stephen Walther

Informazioni su come creare unit test per le azioni del controller. In questa esercitazione Stephen Walther illustra come verificare se un'azione del controller restituisce una determinata visualizzazione, restituisce un determinato set di dati o restituisce un tipo diverso di risultato dell'azione.

L'obiettivo di questa esercitazione è illustrare come scrivere unit test per i controller nelle applicazioni MVC ASP.NET. Viene illustrato come creare tre tipi diversi di unit test. Si apprenderà come testare la visualizzazione restituita da un'azione del controller, come testare i dati di visualizzazione restituiti da un'azione del controller e come verificare se un'azione del controller reindirizza l'utente a una seconda azione del controller.

Creazione del controller in fase di test

Per iniziare, creare il controller che si intende testare. Il controller, denominato , è contenuto nell'elenco ProductController1.

Elenco 1 : ProductController.cs

using System;
using System.Web.Mvc;

namespace Store.Controllers
{
     public class ProductController : Controller
     {
          public ActionResult Index()
          {
               // Add action logic here
               throw new NotImplementedException();
          }

          public ActionResult Details(int Id)
          {

               return View("Details");
          }
     }
}

ProductController Contiene due metodi di azione denominati Index() e Details(). Entrambi i metodi di azione restituiscono una visualizzazione. Si noti che l'azione Details() accetta un parametro denominato ID.

Test della visualizzazione restituita da un controller

Si supponga di voler verificare se restituisce ProductController o meno la visualizzazione corretta. Si vuole assicurarsi che, quando viene richiamata l'azione ProductController.Details() , viene restituita la visualizzazione Dettagli. La classe di test nell'elenco 2 contiene uno unit test per il test della visualizzazione restituita dall'azione ProductController.Details() .

Elenco 2 : ProductControllerTest.cs

using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Store.Controllers;

namespace StoreTests.Controllers
{
     [TestClass]
     public class ProductControllerTest
     {
          [TestMethod]
          public void TestDetailsView()
          {
               var controller = new ProductController();
               var result = controller.Details(2) as ViewResult;
               Assert.AreEqual("Details", result.ViewName);

          }
     }
}

La classe in Listing 2 include un metodo di test denominato TestDetailsView(). Questo metodo contiene tre righe di codice. La prima riga di codice crea una nuova istanza della ProductController classe . La seconda riga di codice richiama il metodo di azione del Details() controller. Infine, l'ultima riga di codice controlla se la visualizzazione restituita dall'azione Details() è la visualizzazione Dettagli.

La ViewResult.ViewName proprietà rappresenta il nome della visualizzazione restituita da un controller. Un grande avviso relativo al test di questa proprietà. Esistono due modi in cui un controller può restituire una visualizzazione. Un controller può restituire in modo esplicito una visualizzazione simile alla seguente:

public ActionResult Details(int Id)
{
     return View("Details");
}

In alternativa, il nome della visualizzazione può essere dedotto dal nome dell'azione del controller come segue:

public ActionResult Details(int Id)
{
     return View();
}

Questa azione del controller restituisce anche una vista denominata Details. Tuttavia, il nome della visualizzazione viene dedotto dal nome dell'azione. Se si vuole testare il nome della visualizzazione, è necessario restituire in modo esplicito il nome della visualizzazione dall'azione del controller.

È possibile eseguire lo unit test nell'elenco 2 immettendo la combinazione di tastiera CTRL-R, A o facendo clic sul pulsante Esegui tutti i test nella soluzione (vedere la figura 1). Se il test viene superato, verrà visualizzata la finestra Risultati test nella figura 2.

Eseguire tutti i test nella soluzione

Figura 01: Eseguire tutti i test nella soluzione (fare clic per visualizzare l'immagine a dimensione intera)

Successo!

Figura 02: Operazione riuscita (Fare clic per visualizzare l'immagine a dimensione intera)

Test dei dati di visualizzazione restituiti da un controller

Un controller MVC passa i dati a una visualizzazione usando un elemento denominato View Data. Si supponga, ad esempio, di voler visualizzare i dettagli di un determinato prodotto quando si richiama l'azione ProductController Details() . In tal caso, è possibile creare un'istanza di una Product classe (definita nel modello) e passare l'istanza alla Details visualizzazione sfruttando i vantaggi di View Data.

L'elemento modificato ProductController nell'elenco 3 include un'azione aggiornata Details() che restituisce un prodotto.

Listato 3 : ProductController.cs

using System;
using System.Web.Mvc;

namespace Store.Controllers
{
     public class ProductController : Controller
     {
          public ActionResult Index()
          {
               // Add action logic here
               throw new NotImplementedException();
          }

          public ActionResult Details(int Id)
          {
               var product = new Product(Id, "Laptop");
               return View("Details", product);
          }
     }
}

Innanzitutto, l'azione Details() crea una nuova istanza della Product classe che rappresenta un computer portatile. Successivamente, l'istanza della Product classe viene passata come secondo parametro al View() metodo .

È possibile scrivere unit test per verificare se i dati previsti sono contenuti nei dati di visualizzazione. Lo unit test nell'elenco 4 verifica se un prodotto che rappresenta un computer portatile viene restituito quando si chiama il ProductController Details() metodo di azione.

Elenco 4 : ProductControllerTest.cs

using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Store.Controllers;

namespace StoreTests.Controllers
{
     [TestClass]
     public class ProductControllerTest
     {

          [TestMethod]
          public void TestDetailsViewData()
          {
               var controller = new ProductController();
               var result = controller.Details(2) as ViewResult;
               var product = (Product) result.ViewData.Model;
               Assert.AreEqual("Laptop", product.Name);
          }
     }
}

Nell'elenco 4 il TestDetailsView() metodo verifica i dati di visualizzazione restituiti richiamando il Details() metodo . L'oggetto ViewData viene esposto come proprietà sull'oggetto ViewResult restituito richiamando il Details() metodo . La ViewData.Model proprietà contiene il prodotto passato alla visualizzazione. Il test verifica semplicemente che il prodotto contenuto in View Data abbia il nome Laptop.

Test del risultato dell'azione restituito da un controller

Un'azione controller più complessa potrebbe restituire diversi tipi di risultati dell'azione a seconda dei valori dei parametri passati all'azione del controller. Un'azione del controller può restituire un'ampia gamma di tipi di risultati dell'azione, tra cui , ViewResultRedirectToRouteResulto JsonResult.

Ad esempio, l'azione modificata Details() in Listato 5 restituisce la Details visualizzazione quando si passa un ID prodotto valido all'azione. Se si passa un ID prodotto non valido, un ID con un valore minore di 1, viene eseguito il reindirizzamento all'azione Index() .

Elenco 5 : ProductController.cs

using System;
using System.Web.Mvc;
namespace Store.Controllers
{
     public class ProductController : Controller
     {
          public ActionResult Index()
          {
               // Add action logic here
               throw new NotImplementedException();
          }
          public ActionResult Details(int Id)
          {
               if (Id < 1)
                    return RedirectToAction("Index");
               var product = new Product(Id, "Laptop");
               return View("Details", product);

          }
     }
}

È possibile testare il comportamento dell'azione Details() con lo unit test nell'elenco 6. Lo unit test nell'elenco 6 verifica di essere reindirizzato alla Index visualizzazione quando viene passato un ID con il valore -1 al Details() metodo .

Elenco 6 : ProductControllerTest.cs

using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Store.Controllers;
namespace StoreTests.Controllers
{
     [TestClass]
     public class ProductControllerTest
     {
          [TestMethod]
          public void TestDetailsRedirect()
          {
               var controller = new ProductController();
               var result = (RedirectToRouteResult) controller.Details(-1);
               Assert.AreEqual("Index", result.Values["action"]);

          }
     }
}

Quando si chiama il RedirectToAction() metodo in un'azione del controller, l'azione del controller restituisce un oggetto RedirectToRouteResult. Il test controlla se reindirizzerà RedirectToRouteResult l'utente a un'azione del controller denominata Index.

Riepilogo

In questa esercitazione si è appreso come compilare unit test per le azioni del controller MVC. In primo luogo, si è appreso come verificare se la visualizzazione corretta viene restituita da un'azione del controller. Si è appreso come usare la ViewResult.ViewName proprietà per verificare il nome di una visualizzazione.

Successivamente, è stato esaminato come testare il contenuto di View Data. Si è appreso come verificare se il prodotto corretto è stato restituito dopo View Data aver chiamato un'azione del controller.

Infine, è stato illustrato come verificare se diversi tipi di risultati dell'azione vengono restituiti da un'azione del controller. Si è appreso come verificare se un controller restituisce o ViewResult .RedirectToRouteResult