Pruebas unitarias de ASP.NET Web API 2

por Tom FitzMacken

Descargar el proyecto completado

En esta guía y aplicación se muestra cómo crear pruebas unitarias sencillas para la aplicación de Web API 2. En este tutorial se muestra cómo incluir un proyecto de prueba unitaria en la solución y escribir métodos de prueba que comprueban los valores devueltos desde un método de controlador.

En este tutorial, se da por supuesto que está familiarizado con los conceptos básicos de ASP.NET Web API. Para ver un tutorial introductorio, consulte Introducción a ASP.NET Web API 2.

Las pruebas unitarias de este tema se limitan intencionadamente a escenarios de datos simples. Para ver escenarios de datos más avanzados de pruebas unitarias, consulte Cómo simular Entity Framework al realizar pruebas unitarias de ASP.NET Web API 2.

Versiones de software usadas en el tutorial

En este tema

Este tema contiene las siguientes secciones:

Requisitos previos

Visual Studio 2017 edición Community, Professional o Enterprise

Descarga de código

Descargue el proyecto completado. El proyecto descargable incluye código de prueba unitaria para este tema y para el tema Cómo simular Entity Framework al realizar pruebas unitarias de ASP.NET Web API 2.

Creación de aplicación con proyecto de prueba unitaria

Puede crear un proyecto de prueba unitaria al crear la aplicación o agregar un proyecto de prueba unitaria a una aplicación existente. En este tutorial se muestran ambos métodos para crear un proyecto de prueba unitaria. Para seguir este tutorial, puede usar cualquiera de los enfoques.

Adición de un proyecto de prueba unitaria al crear la aplicación

Cree una aplicación web de ASP.NET llamada StoreApp.

create project

En la ventana Nuevo proyecto de ASP.NET, seleccione la plantilla Vacía y agregue las carpetas y referencias básicas de Web API. Seleccione la opción Agregar pruebas unitarias. Se asigna automáticamente el nombre StoreApp.Tests al proyecto de prueba unitaria. Puede conservar este nombre.

create unit test project

Después de crear la aplicación, verá que contiene dos proyectos.

two projects

Adición de un proyecto de prueba unitaria a una aplicación existente

Si no creó el proyecto de prueba unitaria al crear la aplicación, puede agregarlo en cualquier momento. Por ejemplo, supongamos que ya tiene una aplicación denominada StoreApp y quiere agregar pruebas unitarias. Para agregar un proyecto de prueba unitaria, haga clic con el botón derecho en la solución y seleccione Agregar y Nuevo proyecto.

add new project to solution

Seleccione Prueba en el panel izquierdo y seleccione Proyecto de prueba unitaria para el tipo de proyecto. Asigne al proyecto el nombre StoreApp.Tests.

add unit test project

Verá el proyecto de prueba unitaria en la solución.

En el proyecto de prueba unitaria, agregue una referencia de proyecto al proyecto original.

Configuración de la aplicación Web API 2

En el proyecto StoreApp, agregue un archivo de clase a la carpeta Models llamado Product.cs. Reemplace el contenido del archivo por el código siguiente.

using System;

namespace StoreApp.Models
{
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
    }
}

Compile la solución.

Haga clic con el botón derecho en la carpeta Controladores y seleccione Agregar y Nuevo elemento con scaffolding. Seleccione Controlador de Web API 2: vacío.

add new controller

Establezca el nombre del controlador en SimpleProductController y haga clic en Agregar.

specify controller

Reemplace el código existente por el siguiente código. Para simplificar este ejemplo, los datos se almacenan en una lista en lugar de en una base de datos. La lista definida en esta clase representa los datos de producción. Observe que el controlador incluye un constructor que toma como parámetro una lista de objetos Product. Este constructor permite pasar datos de prueba al realizar pruebas unitarias. El controlador también incluye dos métodos asincrónicos para ilustrar los métodos asincrónicos de pruebas unitarias. Estos métodos asincrónicos se implementaron llamando a Task.FromResult para minimizar el código extraño, pero normalmente los métodos incluirían operaciones que consumen muchos recursos.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Http;
using StoreApp.Models;

namespace StoreApp.Controllers
{
    public class SimpleProductController : ApiController
    {
        List<Product> products = new List<Product>();        
           
        public SimpleProductController() { }

        public SimpleProductController(List<Product> products)
        {
            this.products = products;
        }

        public IEnumerable<Product> GetAllProducts()
        {
            return products;
        }

        public async Task<IEnumerable<Product>> GetAllProductsAsync()
        {
            return await Task.FromResult(GetAllProducts());
        }

        public IHttpActionResult GetProduct(int id)
        {
            var product = products.FirstOrDefault((p) => p.Id == id);
            if (product == null)
            {
                return NotFound();
            }
            return Ok(product);
        }

        public async Task<IHttpActionResult> GetProductAsync(int id)
        {
            return await Task.FromResult(GetProduct(id));
        }
    }
}

El método GetProduct devuelve una instancia de la interfaz IHttpActionResult. IHttpActionResult es una de las nuevas características de Web API 2 que simplifica el desarrollo de pruebas unitarias. Las clases que implementan la interfaz IHttpActionResult se encuentran en el espacio de nombres System.Web.Http.Results. Estas clases representan posibles respuestas de una solicitud de acción y corresponden a códigos de estado HTTP.

Compile la solución.

Ya está listo para configurar el proyecto de prueba.

Instalación de paquetes NuGet en el proyecto de prueba

Cuando se usa la plantilla Vacía para crear una aplicación, el proyecto de prueba unitaria (StoreApp.Tests) no incluye los paquetes NuGet instalados. Otras plantillas, como la plantilla Web API, incluyen algunos paquetes NuGet en el proyecto de prueba unitaria. Para este tutorial, debe incluir el paquete Microsoft ASP.NET Web API 2 Core en el proyecto de prueba.

Haga clic con el botón derecho en el proyecto StoreApp.Tests y seleccione Administrar paquetes NuGet. Debe seleccionar el proyecto StoreApp.Tests para agregar los paquetes a ese proyecto.

manage packages

Busque e instale el paquete Microsoft ASP.NET Web API 2 Core.

install web api core package

Cierre la ventana Administrar paquetes NuGet.

Crear pruebas

De manera predeterminada, el proyecto de prueba incluye un archivo de prueba vacío llamado UnitTest1.cs. Este archivo muestra los atributos que se usan para crear métodos de prueba. Para las pruebas unitarias, puede usar este archivo o crear su propio archivo.

UnitTest1

En este tutorial, creará su propia clase de prueba. Puede eliminar el archivo UnitTest1.cs. Agregue una clase denominada TestSimpleProductController.cs y reemplace el código por el código siguiente.

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Web.Http.Results;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using StoreApp.Controllers;
using StoreApp.Models;

namespace StoreApp.Tests
{
    [TestClass]
    public class TestSimpleProductController
    {
        [TestMethod]
        public void GetAllProducts_ShouldReturnAllProducts()
        {
            var testProducts = GetTestProducts();
            var controller = new SimpleProductController(testProducts);

            var result = controller.GetAllProducts() as List<Product>;
            Assert.AreEqual(testProducts.Count, result.Count);
        }

        [TestMethod]
        public async Task GetAllProductsAsync_ShouldReturnAllProducts()
        {
            var testProducts = GetTestProducts();
            var controller = new SimpleProductController(testProducts);

            var result = await controller.GetAllProductsAsync() as List<Product>;
            Assert.AreEqual(testProducts.Count, result.Count);
        }

        [TestMethod]
        public void GetProduct_ShouldReturnCorrectProduct()
        {
            var testProducts = GetTestProducts();
            var controller = new SimpleProductController(testProducts);

            var result = controller.GetProduct(4) as OkNegotiatedContentResult<Product>;
            Assert.IsNotNull(result);
            Assert.AreEqual(testProducts[3].Name, result.Content.Name);
        }

        [TestMethod]
        public async Task GetProductAsync_ShouldReturnCorrectProduct()
        {
            var testProducts = GetTestProducts();
            var controller = new SimpleProductController(testProducts);

            var result = await controller.GetProductAsync(4) as OkNegotiatedContentResult<Product>;
            Assert.IsNotNull(result);
            Assert.AreEqual(testProducts[3].Name, result.Content.Name);
        }

        [TestMethod]
        public void GetProduct_ShouldNotFindProduct()
        {
            var controller = new SimpleProductController(GetTestProducts());

            var result = controller.GetProduct(999);
            Assert.IsInstanceOfType(result, typeof(NotFoundResult));
        }

        private List<Product> GetTestProducts()
        {
            var testProducts = new List<Product>();
            testProducts.Add(new Product { Id = 1, Name = "Demo1", Price = 1 });
            testProducts.Add(new Product { Id = 2, Name = "Demo2", Price = 3.75M });
            testProducts.Add(new Product { Id = 3, Name = "Demo3", Price = 16.99M });
            testProducts.Add(new Product { Id = 4, Name = "Demo4", Price = 11.00M });

            return testProducts;
        }
    }
}

Ejecutar pruebas

Ya está listo para ejecutar las pruebas. Se probarán todos los métodos marcados con el atributo TestMethod. En el elemento de menú Probar, ejecute las pruebas.

run tests

Abra la ventana Explorador de pruebas y observe los resultados de las pruebas.

test results

Resumen

Ha completado este tutorial. Los datos de este tutorial se simplificaron intencionadamente para centrarse en las condiciones de pruebas unitarias. Para ver escenarios de datos más avanzados de pruebas unitarias, consulte Cómo simular Entity Framework al realizar pruebas unitarias de ASP.NET Web API 2.