Pruebas unitarias en un Controlador MVC de ASP.NET Core
Continuando con la serie de Posts dedicados a las pruebas unitarias, y para finalizar esta primera entrega, a continuación veremos como realizar tests unitarios a un Controlador ASP.NET MVC en .NET Core.
Cabe resaltar que en este ejemplo, reutilizaremos la gran mayoría del contenido usado en el Post Pruebas unitarias en un servicio Web API RESTful de .NET Core, siendo la única diferencia el tipo de Controlador sobre el que realizaremos los test, y las pruebas unitarias en sí.
El escenario de pruebas
En primer lugar crearemos la clase "controladora" ASP.NET Core MVC sobre la cual realizaremos las pruebas unitarias posteriormente (PaisController.cs
). Este "Controller" se encargará de realizar las operaciones básicas de acceso a datos (CRUD) sobre una entidad de modelo de ejemplo (Pais.cs
), a través del servicio asíncrono PaisesDataService.cs
.
Siguiendo el patrón MVC, para cada una de las Acciones del Controlador deberá existir su correspondiente Vista. En este caso, no entraremos a explicar como construir las Vistas ya que no es ese el objetivo de este Post, y daremos por sentado que ya existen: Index.cshtml
, Create.cshtml
, Edit.cshtml
, Details.cshtml
, Delete.cshtml
.
public class PaisController : Controller
{
private readonly IPaisesDataService paisesDataService;
public PaisController(IPaisesDataService paisesDataService)
{
this.paisesDataService = paisesDataService;
}
// GET: Pais
public async Task<IActionResult> Index()
{
return View("Index", await paisesDataService.ReadPaises());
}
// GET: Pais/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
// NotFound Response Status 404.
return NotFound();
}
var pais = await paisesDataService.ReadPais(id.Value);
if (pais == null)
{
// NotFound Response Status 404.
return NotFound();
}
return View("Details", pais);
}
// GET: Pais/Create
public IActionResult Create()
{
return View("Create");
}
// POST: Pais/Create
// To protect from overposting attacks, please enable the specific properties you want to
// bind to, for more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,Nombre,Habitantes")] Pais pais)
{
if (ModelState.IsValid)
{
if (await paisesDataService.CreatePais(pais) == 0)
{
// NotFound Response Status 404.
return NotFound();
}
return RedirectToAction(nameof(Index));
}
return View("Create", pais);
}
// GET: Pais/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
// NotFound Response Status 404.
return NotFound();
}
var pais = await paisesDataService.ReadPais(id.Value);
if (pais == null)
{
// NotFound Response Status 404.
return NotFound();
}
return View("Edit", pais);
}
// POST: Pais/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to
// bind to, for more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("Id,Nombre,Habitantes")] Pais pais)
{
if (id != pais.Id)
{
// NotFound Response Status 404.
return NotFound();
}
if (ModelState.IsValid)
{
if (await paisesDataService.UpdatePais(pais) == 0)
{
// NotFound Response Status 404.
return NotFound();
}
return RedirectToAction(nameof(Index));
}
return View("Edit", pais);
}
// GET: Pais/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
// NotFound Response Status 404.
return NotFound();
}
var pais = await paisesDataService.ReadPais(id.Value);
if (pais == null)
{
// NotFound Response Status 404.
return NotFound();
}
return View("Delete", pais);
}
// POST: Pais/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
if (await paisesDataService.DeletePais(id) == 0)
{
// NotFound Response Status 404.
return NotFound();
}
return RedirectToAction(nameof(Index));
}
}
Como podemos observar en el código, el controlador PaisController
recibe como parámetro en el constructor, una instancia del servicio de acceso a datos PaisesDataService
a través de su interfaz IPaisesDataService
.
public interface IPaisesDataService
{
Task<int> CreatePais(Pais pais);
Task<Pais> ReadPais(int id);
Task<IEnumerable<Pais>> ReadPaises();
Task<int> UpdatePais(Pais pais);
Task<int> DeletePais(int id);
}
El servicio PaisesDataService.cs
es exactamente el mismo que ya vimos y explicamos en el Post Pruebas unitarias en Entity Framework Core - SqLite in-memory.
Las pruebas unitarias
Una vez construido el escenario de pruebas de ejemplo, pasaremos a crear un nuevo proyecto de pruebas unitarias del tipo Proyecto de prueba de MSTest(.NET Core). Para este ejemplo se ha utilizado Visual Studio Community 2017 (con todas las actualizaciones al día).
Por supuesto, es necesario añadir una referencia (dependencia) al proyecto sobre el que vamos a realizar las pruebas (el escenario de pruebas anteriormente creado).
El servicio de acceso a datos de pruebas (Fake)
Para realizar las pruebas unitarias, necesitamos "simular" un entorno de acceso a datos que implemente la interfaz IPaisesDataService
. Este entorno o servicio ficticio (Fake) será "inyectado" a través del constructor del Controlador (PaisController
) a la hora de realizar las pruebas unitarias, y deberá proporcionar la misma funcionalidad que el servicio PaisesDataService
nos ofrecería en un entorno real de producción.
public class PaisesDataServiceFake : IPaisesDataService
{
private SqLiteDbFake sqLiteDbFake;
public PaisesDataServiceFake()
{
sqLiteDbFake = new SqLiteDbFake();
using (var context = sqLiteDbFake.GetDbContext())
{
context.Paises.Add(new Pais { Id = 1, Nombre = "España", Habitantes = 1000, Provincias = new List<Provincia>() });
context.Paises.Add(new Pais { Id = 2, Nombre = "Francia", Habitantes = 1000, Provincias = new List<Provincia>() });
context.Paises.Add(new Pais { Id = 3, Nombre = "Italia", Habitantes = 1000, Provincias = new List<Provincia>() });
context.SaveChangesAsync();
}
}
public async Task<int> CreatePais(Pais pais)
{
using (var context = sqLiteDbFake.GetDbContext())
{
context.Paises.Add(pais);
try
{
return await context.SaveChangesAsync();
}
catch (Exception)
{
return 0;
}
}
}
public async Task<Pais> ReadPais(int id)
{
using (var context = sqLiteDbFake.GetDbContext())
{
return await context.Paises.Include(x => x.Provincias).SingleOrDefaultAsync(m => m.Id == id);
}
}
public async Task<IEnumerable<Pais>> ReadPaises()
{
using (var context = sqLiteDbFake.GetDbContext())
{
return await context.Paises.ToListAsync();
}
}
public async Task<int> UpdatePais(Pais pais)
{
using (var context = sqLiteDbFake.GetDbContext())
{
context.Entry(pais).State = EntityState.Modified;
try
{
return await context.SaveChangesAsync();
}
catch (Exception)
{
return 0;
}
}
}
public async Task<int> DeletePais(int id)
{
using (var context = sqLiteDbFake.GetDbContext())
{
var pais = context.Paises.SingleOrDefault(m => m.Id == id);
try
{
context.Paises.Remove(pais);
return await context.SaveChangesAsync();
}
catch (Exception)
{
return 0;
}
}
}
}
Como podemos ver, el servicio de pruebas PaisesDataServiceFake.cs
, simula un entorno de acceso a datos CRUD sobre una base de datos en memoria SqLite in-memory. Todo lo relativo a cómo crear bases de datos en memoria y a la clase SqLiteDbFake.cs
, se puede ver en el Post Pruebas unitarias en Entity Framework Core - SqLite in-memory.
La clase de pruebas unitarias (TestClass)
Por último, crearemos las clase de pruebas unitarias (PaisControllerTests.cs
) para el controlador MVC PaisController.cs
.
[TestClass]
public class PaisControllerTests
{
// Servicio de acceso a datos Fake.
private PaisesDataServiceFake paisesDataServiceFake;
public PaisControllerTests()
{
paisesDataServiceFake = new PaisesDataServiceFake();
}
...
...
// Aquí todas las pruebas unitarias...
...
...
}
Como vemos en el código, en el constructor de la clase PaisControllerTests
instanciamos un objeto del servicio de pruebas PaisesDataServiceFake
, el cual utilizaremos posteriormente para realizar las pruebas unitarias (TestMethod
).
Programando las pruebas unitarias (TestMethod)
Para obtener una mejor legibilidad del código y una estructura fácilmente mantenible, organizaremos las pruebas en función de su cometido. En nuestro caso las dividiremos en pruebas Index, Create, Details, Edit y Delete.
Debemos tener también en cuenta que los nombres de las pruebas deben de ser lo suficientemente descriptivos como para saber a primera vista cual es su función.
Pruebas Index
[TestMethod]
public void Index_GET_Retorna_Vista_Index_con_todos_los_registros_de_la_BD_Async()
{
// Arrange
string expectedView = "Index";
var paisController = new PaisController(paisesDataServiceFake);
// Act
var actionResult = paisController.Index().Result as ViewResult;
// Assert
Assert.IsNotNull(actionResult,
"El ActionResult no debe ser Null.");
Assert.IsInstanceOfType(actionResult, typeof(ViewResult),
"El ActionResult debe ser del tipo ViewResult.");
Assert.AreEqual(actionResult.ViewName, expectedView,
"El nombre de la Vista devuelta debe ser " + expectedView);
Assert.IsInstanceOfType(actionResult.Model, typeof(IEnumerable<Pais>),
"El Modelo pasado a la Vista debe ser del tipo IEnumerable<Pais>.");
Assert.AreEqual(3, (actionResult.Model as IEnumerable<Pais>).Count(),
"El Modelo pasado a la Vista contiene todos los registros de la BD.");
}
Como podemos observar en las pruebas, cada vez que instanciemos el controlador MVC para probar la funcionalidad de alguna de sus acciones, le pasaremos a través del constructor la instancia del servicio de acceso a datos de pruebas (Fake) var paisController = new PaisController(paisesDataServiceFake)
.
Para el resto de las pruebas unitarias, el procedimiento será básicamente el mismo.
Pruebas Details
[TestMethod]
public void Details_GET_Retorna_Vista_Details_con_registro_existente_en_la_BD_Async()
{
// Arrange
string expectedView = "Details";
var paisController = new PaisController(paisesDataServiceFake);
// Act
var actionResult = paisController.Details(1).Result as ViewResult;
// Assert
Assert.IsNotNull(actionResult,
"El ActionResult no debe ser Null.");
Assert.IsInstanceOfType(actionResult, typeof(ViewResult),
"El ActionResult debe ser del tipo ViewResult.");
Assert.AreEqual(actionResult.ViewName, expectedView,
"El nombre de la Vista devuelta debe ser " + expectedView);
Assert.IsInstanceOfType(actionResult.Model, typeof(Pais),
"El Modelo pasado a la Vista debe ser del tipo Pais.");
Assert.AreEqual(1, (actionResult.Model as Pais).Id,
"El Id del Modelo pasado a la Vista es el correcto.");
}
[TestMethod]
public void Details_GET_Retorna_NotFoundResult_al_pasar_Id_Null_Async()
{
// Arrange
var paisController = new PaisController(paisesDataServiceFake);
// Act
var actionResult = paisController.Details(null).Result as NotFoundResult;
// Assert
Assert.IsNotNull(actionResult,
"El ActionResult no debe ser Null.");
Assert.IsInstanceOfType(actionResult, typeof(NotFoundResult),
"El ActionResult debe ser del tipo NotFoundResult.");
}
[TestMethod]
public void Details_GET_Retorna_NotFoundResult_al_pasar_Id_inexistente_Async()
{
// Arrange
var paisController = new PaisController(paisesDataServiceFake);
// Act
var actionResult = paisController.Details(0).Result as NotFoundResult;
// Assert
Assert.IsNotNull(actionResult,
"El ActionResult no debe ser Null.");
Assert.IsInstanceOfType(actionResult, typeof(NotFoundResult),
"El ActionResult debe ser del tipo NotFoundResult.");
}
Pruebas Create
[TestMethod]
public void Create_GET_Retorna_Vista_Create()
{
// Arrange
string expectedView = "Create";
var paisController = new PaisController(paisesDataServiceFake);
// Act
var actionResult = paisController.Create() as ViewResult;
// Assert
Assert.IsNotNull(actionResult,
"El ActionResult no debe ser Null.");
Assert.IsInstanceOfType(actionResult, typeof(ViewResult),
"El ActionResult debe ser del tipo ViewResult.");
Assert.AreEqual(actionResult.ViewName, expectedView,
"El nombre de la Vista devuelta debe ser " + expectedView);
}
[TestMethod]
public void Create_POST_Retorna_NotFoundResult_si_el_objeto_no_puede_ser_creado_en_BD_Async()
{
// Arrange
var pais = new Pais();
pais.Id = 1; // Id existente en BD.
pais.Nombre = "PaisPruebas";
pais.Habitantes = 1000;
pais.Provincias = new List<Provincia>();
var paisController = new PaisController(paisesDataServiceFake);
// Act
var actionResult = paisController.Create(pais).Result as NotFoundResult;
// Assert
Assert.IsNotNull(actionResult,
"El ActionResult no debe ser Null.");
Assert.IsInstanceOfType(actionResult, typeof(NotFoundResult),
"El ActionResult debe ser del tipo NotFoundResult.");
Assert.AreEqual(3, paisesDataServiceFake.ReadPaises().Result.Count(),
"No se ha creado el registro en la BD.");
}
[TestMethod]
public void Create_POST_Retorna_Vista_Create_con_Modelo_al_pasar_Modelo_invalido_Async()
{
// Arrange
string expectedView = "Create";
var pais = new Pais();
pais.Id = 4;
pais.Nombre = null; // Nombre no puede ser Null.
pais.Habitantes = 1000;
pais.Provincias = new List<Provincia>();
var paisController = new PaisController(paisesDataServiceFake);
// Añadir el error para que el ModelState.IsValid lo detecte
// antes de añadir el registro a la BD.
paisController.ModelState.AddModelError("Nombre", "Required");
// Act
var actionResult = paisController.Create(pais).Result as ViewResult;
// Assert
Assert.IsNotNull(actionResult,
"El ActionResult no debe ser Null.");
Assert.IsInstanceOfType(actionResult, typeof(ViewResult),
"El ActionResult debe ser del tipo ViewResult.");
Assert.AreEqual(actionResult.ViewName, expectedView,
"El nombre de la Vista devuelta debe ser " + expectedView);
Assert.AreEqual(pais, actionResult.Model,
"El Modelo pasado a la Vista es el Modelo inválido.");
Assert.AreEqual(3, paisesDataServiceFake.ReadPaises().Result.Count(),
"No se ha creado el registro en la BD.");
}
[TestMethod]
public void Create_POST_Retorna_Vista_Index_al_crear_un_objeto_valido_en_BD_Async()
{
// Arrange
string expectedView = "Index";
var pais = new Pais();
pais.Id = 4;
pais.Nombre = "PaisPruebas";
pais.Habitantes = 1000;
pais.Provincias = new List<Provincia>();
var paisController = new PaisController(paisesDataServiceFake);
// Act
var actionResult = paisController.Create(pais).Result as RedirectToActionResult;
// Assert
Assert.IsNotNull(actionResult,
"El ActionResult no debe ser Null.");
Assert.IsInstanceOfType(actionResult, typeof(RedirectToActionResult),
"El ActionResult debe ser del tipo RedirectToActionResult.");
Assert.AreEqual(actionResult.ActionName, expectedView,
"El nombre de la Vista devuelta debe ser " + expectedView);
Assert.AreEqual(4, paisesDataServiceFake.ReadPaises().Result.Count(),
"Se ha creado un nuevo registro en la BD.");
Assert.AreEqual(pais.Nombre, paisesDataServiceFake.ReadPais(4).Result.Nombre,
"El nombre del nuevo registro creado es el correcto.");
}
Pruebas Edit
[TestMethod]
public void Edit_GET_Retorna_Vista_Edit_con_registro_existente_en_la_BD_Async()
{
// Arrange
string expectedView = "Edit";
var paisController = new PaisController(paisesDataServiceFake);
// Act
var actionResult = paisController.Edit(1).Result as ViewResult;
// Assert
Assert.IsNotNull(actionResult,
"El ActionResult no debe ser Null.");
Assert.IsInstanceOfType(actionResult, typeof(ViewResult),
"El ActionResult debe ser del tipo ViewResult.");
Assert.AreEqual(actionResult.ViewName, expectedView,
"El nombre de la Vista devuelta debe ser " + expectedView);
Assert.IsInstanceOfType(actionResult.Model, typeof(Pais),
"El Modelo pasado a la Vista debe ser del tipo Pais.");
Assert.AreEqual(1, (actionResult.Model as Pais).Id,
"El Id del Modelo pasado a la Vista es el correcto.");
}
[TestMethod]
public void Edit_GET_Retorna_NotFoundResult_al_pasar_Id_Null_Async()
{
// Arrange
var paisController = new PaisController(paisesDataServiceFake);
// Act
var actionResult = paisController.Edit(null).Result as NotFoundResult;
// Assert
Assert.IsNotNull(actionResult,
"El ActionResult no debe ser Null.");
Assert.IsInstanceOfType(actionResult, typeof(NotFoundResult),
"El ActionResult debe ser del tipo NotFoundResult.");
}
[TestMethod]
public void Edit_GET_Retorna_NotFoundResult_al_pasar_Id_inexistente_Async()
{
// Arrange
var paisController = new PaisController(paisesDataServiceFake);
// Act
var actionResult = paisController.Details(0).Result as NotFoundResult;
// Assert
Assert.IsNotNull(actionResult,
"El ActionResult no debe ser Null.");
Assert.IsInstanceOfType(actionResult, typeof(NotFoundResult),
"El ActionResult debe ser del tipo NotFoundResult.");
}
[TestMethod]
public void Edit_POST_Retorna_NotFoundResult_si_el_objeto_no_puede_ser_modificado_en_BD_Async()
{
// Arrange
var pais = new Pais();
pais.Id = 1;
pais.Nombre = "PaisPruebasEdit";
pais.Habitantes = 1000;
pais.Provincias = new List<Provincia>();
var paisController = new PaisController(paisesDataServiceFake);
// Act
var actionResult = paisController.Edit(4, pais).Result as NotFoundResult;
// Assert
Assert.IsNotNull(actionResult,
"El ActionResult no debe ser Null.");
Assert.IsInstanceOfType(actionResult, typeof(NotFoundResult),
"El ActionResult debe ser del tipo NotFoundResult.");
Assert.AreNotEqual(pais.Nombre, paisesDataServiceFake.ReadPais(1).Result.Nombre,
"No se ha modificado el registro en la BD.");
}
[TestMethod]
public void Edit_POST_Retorna_Vista_Edit_con_Modelo_al_pasar_Modelo_invalido_Async()
{
// Arrange
string expectedView = "Edit";
var pais = new Pais();
pais.Id = 1;
pais.Nombre = null; // Nombre no puede ser Null.
pais.Habitantes = 1000;
pais.Provincias = new List<Provincia>();
var paisController = new PaisController(paisesDataServiceFake);
// Añadir el error para que el ModelState.IsValid lo detecte
// antes de añadir el registro a la BD.
paisController.ModelState.AddModelError("Nombre", "Required");
// Act
var actionResult = paisController.Edit(1, pais).Result as ViewResult;
// Assert
Assert.IsNotNull(actionResult,
"El ActionResult no debe ser Null.");
Assert.IsInstanceOfType(actionResult, typeof(ViewResult),
"El ActionResult debe ser del tipo ViewResult.");
Assert.AreEqual(actionResult.ViewName, expectedView,
"El nombre de la Vista devuelta debe ser " + expectedView);
Assert.AreEqual(pais, actionResult.Model,
"El Modelo pasado a la Vista es el Modelo inválido.");
Assert.AreNotEqual(pais.Nombre, paisesDataServiceFake.ReadPais(1).Result.Nombre,
"No se ha modificado el registro en la BD.");
}
[TestMethod]
public void Edit_POST_Retorna_Vista_Index_al_modificar_un_objeto_existente_en_BD_Async()
{
// Arrange
string expectedView = "Index";
var pais = new Pais();
pais.Id = 1;
pais.Nombre = "PaisPruebasEdit";
pais.Habitantes = 1000;
pais.Provincias = new List<Provincia>();
var paisController = new PaisController(paisesDataServiceFake);
// Act
var actionResult = paisController.Edit(1, pais).Result as RedirectToActionResult;
// Assert
Assert.IsNotNull(actionResult,
"El ActionResult no debe ser Null.");
Assert.IsInstanceOfType(actionResult, typeof(RedirectToActionResult),
"El ActionResult debe ser del tipo RedirectToActionResult.");
Assert.AreEqual(actionResult.ActionName, expectedView,
"El nombre de la Vista devuelta debe ser " + expectedView);
Assert.AreEqual(pais.Nombre, paisesDataServiceFake.ReadPais(1).Result.Nombre,
"El nombre del registro modificado es el correcto.");
}
[TestMethod]
public void Edit_POST_Retorna_NotFoundResult_al_pasar_Id_diferente_al_del_Modelo_Async()
{
// Arrange
var pais = new Pais();
pais.Id = 1;
pais.Nombre = "PaisPruebasEdit";
pais.Habitantes = 1000;
pais.Provincias = new List<Provincia>();
var paisController = new PaisController(paisesDataServiceFake);
// Act
var actionResult = paisController.Edit(0, pais).Result as NotFoundResult;
// Assert
Assert.IsNotNull(actionResult,
"El ActionResult no debe ser Null.");
Assert.IsInstanceOfType(actionResult, typeof(NotFoundResult),
"El ActionResult debe ser del tipo NotFoundResult.");
Assert.AreNotEqual(pais.Nombre, paisesDataServiceFake.ReadPais(1).Result.Nombre,
"No se ha modificado el registro en la BD.");
}
Pruebas Delete
[TestMethod]
public void Delete_GET_Retorna_Vista_Delete_con_registro_existente_en_la_BD_Async()
{
// Arrange
string expectedView = "Delete";
var paisController = new PaisController(paisesDataServiceFake);
// Act
var actionResult = paisController.Delete(1).Result as ViewResult;
// Assert
Assert.IsNotNull(actionResult,
"El ActionResult no debe ser Null.");
Assert.IsInstanceOfType(actionResult, typeof(ViewResult),
"El ActionResult debe ser del tipo ViewResult.");
Assert.AreEqual(actionResult.ViewName, expectedView,
"El nombre de la Vista devuelta debe ser " + expectedView);
Assert.IsInstanceOfType(actionResult.Model, typeof(Pais),
"El Modelo pasado a la Vista debe ser del tipo Pais.");
Assert.AreEqual(1, (actionResult.Model as Pais).Id,
"El Id del Modelo pasado a la Vista es el correcto.");
}
[TestMethod]
public void Delete_GET_Retorna_NotFoundResult_al_pasar_Id_Null_Async()
{
// Arrange
var paisController = new PaisController(paisesDataServiceFake);
// Act
var actionResult = paisController.Delete(null).Result as NotFoundResult;
// Assert
Assert.IsNotNull(actionResult,
"El ActionResult no debe ser Null.");
Assert.IsInstanceOfType(actionResult, typeof(NotFoundResult),
"El ActionResult debe ser del tipo NotFoundResult.");
}
[TestMethod]
public void Delete_GET_Retorna_NotFoundResult_al_pasar_Id_inexistente_Async()
{
// Arrange
var paisController = new PaisController(paisesDataServiceFake);
// Act
var actionResult = paisController.Delete(0).Result as NotFoundResult;
// Assert
Assert.IsNotNull(actionResult,
"El ActionResult no debe ser Null.");
Assert.IsInstanceOfType(actionResult, typeof(NotFoundResult),
"El ActionResult debe ser del tipo NotFoundResult.");
}
[TestMethod]
public void DeleteConfirmed_POST_Retorna_NotFoundResult_si_el_objeto_no_puede_ser_eliminado_de_la_BD_Async()
{
// Arrange
var paisController = new PaisController(paisesDataServiceFake);
// Act
var actionResult = paisController.DeleteConfirmed(4).Result as NotFoundResult;
// Assert
Assert.IsNotNull(actionResult,
"El ActionResult no debe ser Null.");
Assert.IsInstanceOfType(actionResult, typeof(NotFoundResult),
"El ActionResult debe ser del tipo NotFoundResult.");
Assert.AreEqual(3, paisesDataServiceFake.ReadPaises().Result.Count(),
"No se ha eliminado el registro de la BD.");
}
[TestMethod]
public void DeleteConfirmed_POST_Retorna_Vista_Index_al_eliminar_un_objeto_existente_en_BD_Async()
{
// Arrange
string expectedView = "Index";
var paisController = new PaisController(paisesDataServiceFake);
// Act
var actionResult = paisController.DeleteConfirmed(1).Result as RedirectToActionResult;
// Assert
Assert.IsNotNull(actionResult,
"El ActionResult no debe ser Null.");
Assert.IsInstanceOfType(actionResult, typeof(RedirectToActionResult),
"El ActionResult debe ser del tipo RedirectToActionResult.");
Assert.AreEqual(actionResult.ActionName, expectedView,
"El nombre de la Vista devuelta debe ser " + expectedView);
Assert.AreEqual(2, paisesDataServiceFake.ReadPaises().Result.Count(),
"Se ha eliminado el registro de la BD.");
}
Nuevo comentario
Comentarios
Y si los controladores manejan HttpContext?