Leer en inglés

Compartir a través de


Crear pruebas unitarias para aplicaciones de ASP.NET MVC (C#)

de Stephen Walther

Aprenda a crear pruebas unitarias para acciones de controlador. En este tutorial, Stephen Walther realiza una demostración de cómo probar si una acción del controlador devuelve una vista determinada, devuelve un conjunto determinado de datos o devuelve un tipo diferente de resultado de acción.

El objetivo de este tutorial es demostrar cómo escribir pruebas unitarias para los controladores de las aplicaciones de MVC de ASP.NET. Aquí se describirá cómo crear tres tipos diferentes de pruebas unitarias. Aprenderá a probar la vista que devuelve una acción del controlador, a probar el elemento ViewData devuelto por una acción del controlador y a probar si una acción del controlador le redirecciona a una segunda acción del controlador.

Creación del controlador en Prueba

Para empezar, creemos el controlador que pretendemos probar. El controlador, denominado , cuyo nombre es ProductController, se encuentra en la lista 1.

Lista 1: ProductController.cs

C#
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 dos métodos de acción denominados Index() y Details(). Ambos métodos de acción devuelven una vista. Observe que la acción Details() acepta un parámetro denominado Id.

Prueba de la vista devuelta por un controlador

Imagine que queremos probar si ProductController devuelve la vista correcta. Queremos asegurarnos de que cuando se invoca la acción ProductController.Details(), se devuelve la vista Detalles. La clase de prueba de la lista 2 contiene una prueba unitaria para probar la vista devuelta por la acción ProductController.Details().

Lista 2: ProductControllerTest.cs

C#
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 clase de la lista 2 incluye un método de prueba denominado TestDetailsView(). Este método contiene tres líneas de código. La primera línea de código crea una instancia de la clase ProductController. La segunda línea de código invoca el método de acción Details() del controlador. Por su parte, la última línea de código comprueba si la vista que devuelve la acción Details() es la vista Detalles.

La propiedad ViewResult.ViewName representa el nombre de la vista devuelta por un controlador. Una gran advertencia sobre cómo probar esta propiedad. Hay dos formas en que un controlador puede devolver una vista. Un controlador puede devolver explícitamente una vista como esta:

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

Como alternativa, el nombre de la vista se puede deducir del nombre de la acción del controlador de la siguiente manera:

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

Esta acción del controlador también devuelve una vista denominada Details. Sin embargo, el nombre de la vista se deduce del nombre de la acción. Si desea probar el nombre de la vista, debe devolver explícitamente el nombre de la vista de la acción del controlador.

Para ejecutar la prueba unitaria en la lista 2, escriba la combinación de teclas Ctrl-R, A, o bien haga clic en el botón Ejecutar todas las pruebas en la solución (vea la figura 1). Si la prueba arroja resultados satisfactorios, verá la ventana Resultados de pruebas en la figura 2.

Run All Tests in Solution

Figura 01: Ejecutar todas las pruebas en la solución (haga clic para ver la imagen a tamaño completo)

Success!

Figura 02: Correcto (haga clic para ver la imagen a tamaño completo)

Prueba de los datos de vista devueltos por un controlador

Un controlador MVC pasa datos a una vista mediante algo denominado View Data. Por ejemplo, imagine que desea mostrar los detalles de un producto determinado al invocar la acción ProductController Details(). En ese caso, puede crear una instancia de una clase Product (definida en el modelo) y pasar la instancia a la vista Details aprovechando View Data.

La ProductController modificada de la lista 3 incluye una acción Details() actualizada que devuelve un producto.

Lista 3: ProductController.cs

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

En primer lugar, la acción Details() crea una instancia de la clase Product que representa un equipo portátil. A continuación, la instancia de la clase Product se pasa como segundo parámetro al método View().

Puede escribir pruebas unitarias para probar si los datos esperados se encuentran en los datos de vista. La prueba unitaria de la lista 4 comprueba si se devuelve un producto que representa un equipo portátil cuando se llama al método de acción ProductController Details().

Lista 4: ProductControllerTest.cs

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

En la lista 4, el método TestDetailsView() prueba los datos de vista devueltos, para lo que invoca el método Details(). ViewData se expone como una propiedad en el ViewResult devuelto invocando el método Details(). La propiedad ViewData.Model contiene el producto pasado a la vista. La prueba simplemente comprueba que el producto contenido en View Data tiene el nombre Laptop.

Prueba del resultado de la acción devuelto por un controlador

Una acción de controlador más compleja podría devolver diferentes tipos de resultados de acción en función de los valores de los parámetros pasados a la acción del controlador. Una acción del controlador puede devolver una variedad de tipos de resultados de acción, como ViewResult, RedirectToRouteResult o JsonResult.

Por ejemplo, la acción Details() modificada de la lista 5 devuelve la vista Details cuando se pasa un identificador de producto válido a la acción. Si pasa un identificador de producto no válido (un identificador con un valor inferior a 1), se le redirigirá a la acción Index().

Lista 5: ProductController.cs

C#
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);

          }
     }
}

Puede probar el comportamiento de la acción Details() con la prueba unitaria de la lista 6. La prueba unitaria de la lista 6 comprueba que se le redirecciona a la vista Index cuando se pasa un identificador con el valor -1 al método Details().

Lista 6: ProductControllerTest.cs

C#
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"]);

          }
     }
}

Cuando se llama al método RedirectToAction() en una acción de controlador, esta devuelve RedirectToRouteResult. La prueba comprueba si RedirectToRouteResult redireccionará al usuario a una acción de controlador denominada Index.

Resumen

En este tutorial, ha aprendido a crear pruebas unitarias para acciones del controlador de MVC. En primer lugar, ha aprendido a comprobar si una acción de controlador devuelve la vista correcta. Ha aprendido a usar la propiedad ViewResult.ViewName para comprobar el nombre de una vista.

Luego, hemos examinado cómo puede probar el contenido de View Data. Ha aprendido a comprobar si el producto correcto se devolvió en View Data después de llamar a una acción del controlador.

Por último, hemos explicado cómo se puede probar si se devuelven distintos tipos de resultados de acción de una acción del controlador. Ha aprendido a probar si un controlador devuelve ViewResult o RedirectToRouteResult.