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.

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.

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.