Teste Unitário para Controllers no ASP.NET Web API 2 com HttpResponseMessage

Neste artigo vou explicar como desenvolver testes unitários para controllers do ASP.NET Web API 2 que retornam  seus dados em uma resposta HTTP do tipo HttpResponseMessage.

No ASP.NET Web API 2 os métodos no controller podem retornar, por exemplo, dois tipos de resposta HTTP: HttpResponseMessage ou IHttpActionResult. Para entender melhor a diferença entre eles é só dar um olhada nesse outro post que explica melhor como cada um funciona.

Para iniciar vamos criar um objeto de exemplo para usar no repositório.

namespace LuizPauloPradoBlog.Repository.Model
{
    public class Car
    {
        public string Model { get; set; }
        public string Name { get; set; }
        public int YearOfManufacture { get; set; }
    }
}

Depois da criação do objeto de exemplo, basta criar um repositório simples, sem envolver muitos conceitos avançados, que vai persistir nossos dados.

namespace LuizPauloPradoBlog.Repository
{
    public class CarRepository : ICarRepository
    {
       private List<Car> _cars;

        public CarRepository(List<Car> cars)
        {
            _cars = cars;
        }

        public CarRepository()
        {
            _cars = new List<Car>();
        }

        public void Add(Car car)
        {
            _cars.Add(car);
        }

        public Car Get(string model)
        {
            return _cars.FirstOrDefault(x => x.Model == model);
        }

        public IEnumerable<Car> GetAll()
        {
            return _cars;
        }
    }
}

Terminado o repositório, será necessário criar um controller para acessar esses métodos e criar as respostas HTTP usando HttpResponseMessage.

namespace LuizPauloPradoBlog.Repository.Model
namespace LuizPauloPradoBlog.WebApi.Controllers
{
    public class CarController : ApiController
    {
        private ICarRepository _repository;

        public CarController(ICarRepository repository)
        {
            _repository = repository;
        }

        public HttpResponseMessage Get()
        {
            var cars = _repository.GetAll();

            return Request.CreateResponse(cars);
        }

        public HttpResponseMessage Get(string model)
        {
            var car = _repository.Get(model);

            if (car == null)
                return Request.CreateResponse(HttpStatusCode.NotFound);

            return Request.CreateResponse(car);
        }

        public HttpResponseMessage Post(Car car)
        {
            _repository.Add(car);

            return Request.CreateResponse(HttpStatusCode.Created, car);
        }
    }
}

Nosso controller contém alguns métodos de exemplo para listar todos os registros com o Get(), localizar um registro por modelo do carro com o Get(string model) e cadastrar um registro novo com o Post(Car car).

É neste ponto que chegamos onde queremos. Toda estrutura básica de um projeto está criada e finalmente podemos adicionar o projeto de testes que irá validar o comportamento do nosso controller.

Pará adicioná-lo basta clicar com o botão direito do mouse na sua solution e seguir os passos Add > New Project > Test > Unit Test Project.

Captura de Tela 2016-06-07 às 17.55.14

Após a criação do projeto de testes, um passo muito importante é se lembrar de adicionar o pacote Microsft.AspNet.WebApi.Core para que seja possível criar os objetos de controller na nossa classe de testes.

Nosso primeiro teste vai validar o comportamento de selecionar um registro do nosso repositório através do método Get(string model) do controller.

[TestMethod]
public void ShouldGetCar()
{
    var controller = new CarController(_repository);
    controller.Request = new HttpRequestMessage();
    controller.Configuration = new HttpConfiguration();

    var result = controller.Get("Fiesta SE");

    Car car;

    Assert.IsTrue(result.TryGetContentValue<Car>(out car));
    Assert.AreEqual(car.Model, "Fiesta SE");
}

Primeiramente iremos instanciar  o nosso controller e passar como parâmetro um objeto de repositório com os nossos dados de exemplo. Em seguida iremos chamar o método Get(string model) e o seu retorno será armazenado na variável result. Para validar o resultado iremos usar o Assert.IsTrue chamando o método TryGetCurrentValue no nosso objeto result para converter o conteúdo em um objeto do tipo Car. A validação seguinte verifica se objeto car é de fato o registro que foi selecionado no Get(string model) do controller.

Os demais métodos de teste para cada ação do nosso controller seguem a mesma estrutura do exemplo mostrado acima. A diferença está no que está sendo validado. Pode ser um campo do objeto, pode ser a quantidade de registros retornados, ou até mesmo se o objeto é nulo. Acompanhe abaixo a classe de testes com todos os métodos.

namespace LuizPauloPradoBlog.WebApi.Tests
{
    [TestClass]
    public class CarControllerTest
    {
        private ICarRepository _repository;

        [TestInitialize]
        public void Initialize()
        {
            var carSamples = new List<Car>();
            carSamples.Add(new Car() { Name = "Fiesta", Model = "Fiesta SE", YearOfManufacture = 2015 });
            carSamples.Add(new Car() { Name = "Golf", Model = "Golf Sport", YearOfManufacture = 2015 });
            carSamples.Add(new Car() { Name = "Civic", Model = "Civic S", YearOfManufacture = 2016 });

            _repository = new CarRepository(carSamples);
        }

        [TestMethod]
        public void ShouldGetAllCars()
        {
            var controller = new CarController(_repository);
            controller.Request = new HttpRequestMessage();
            controller.Configuration = new HttpConfiguration();

            var result = controller.Get();

            IEnumerable<Car> cars;

            Assert.IsTrue(result.TryGetContentValue<IEnumerable<Car>>(out cars));
            Assert.IsNotNull(cars);
            Assert.AreEqual(3, cars.Count());
        }

        [TestMethod]
        public void ShouldGetCar()
        {
            var controller = new CarController(_repository);
            controller.Request = new HttpRequestMessage();
            controller.Configuration = new HttpConfiguration();

            var result = controller.Get("Fiesta SE");

            Car car;

            Assert.IsTrue(result.TryGetContentValue<Car>(out car));
            Assert.AreEqual(car.Model, "Fiesta SE");
        }

        [TestMethod]
        public void ShouldPostCar()
        {
            var controller = new CarController(_repository);
            controller.Request = new HttpRequestMessage();
            controller.Configuration = new HttpConfiguration();

            var newCar = new Car() { Name = "IX 35", Model = "IX 35 Special", YearOfManufacture = 2016 };

            var result = controller.Post(newCar);

            Car car;

            Assert.IsTrue(result.TryGetContentValue<Car>(out car));
            Assert.IsNotNull(car);
            Assert.AreEqual(car.Name, newCar.Name);
            Assert.AreEqual(car.Model, newCar.Model);
            Assert.AreEqual(car.YearOfManufacture, newCar.YearOfManufacture);
        }
    }
}

O último passo é executar todos os testes e conferir se tudo funcionou corretamente.

Captura de Tela 2016-06-07 às 18.19.49

O projeto completo de exemplo pode ser encontrado no meu GitHub.

Se quiserem conhecer mais sobre mim, basta ir aqui no blog no menu quem sou e conferir também o meu LinkedIn.

Aqui no blog também tem o artigo que explica como fazer esses mesmos testes em um projeto ASP.NET Web API 2 que retorna os dados em um IHttpActionResult.

Se ficou alguma dúvida, ou se algo não funcionou, deixa um comentário aqui no blog que esclareço as dúvidas.

Deixe um comentário