{tecnologia, conceitos, negócios, idéias, práticas, .NET, ruby, osx, ios e algo mais}
30/08/2010
Continuando a falar sobre testes de controllers no ASP.NET MVC, neste post mostrarei como realizar alguns testes para garantir que as actions retornem as views corretas e com os dados corretos.A questão de testar os controllers é que, inevitavelmente, eles possuem comportamentos. Suas actions tomam decisões, sabem falar com partes do nosso domínio, e sabem o que retornam para a exibição e de que forma essa exebição será (escolhendo entre as views disponíveis). Desta forma é importante que tenhamos testes que nos auxiliem neste processo, não apenas na "captura" de bugs (pois acho que testes unitários não atuam dessa forma) mas no auxílio a manutenção e evolução do nosso sistema.
Este teste é um teste simples que mostra como verificar o comportamento de uma action que deve coordenar a listagem de Produtos.
[TestMethod]
public void Action_Listar_Retorna_Todos_Produtos_Para_View_ListarProdutos(){
var todosProdutos = new List<produto> { new Produto("Computador"), new Produto("Teclado"), new Produto("Mouse"), }
;
repositorio .Setup(r => r.Todos()) .Returns(todosProdutos);
var resultView = controller.Listar();
Assert.AreEqual("ListarProdutos", resultView.ViewName);
Assert.IsTrue(resultView.ViewData.Model is List<produto>);
Assert.AreEqual(todosProdutos, resultView.ViewData.Model);
}
</produto></produto>
Neste teste criamos uma lista de produtos e configuramos o mock do nosso repositório para retornar esta lista.Na linha 15 fazemos a chamada para a action Listar do nosso controller.Na linha 17 verificamos se a view retornada é a view ListarProdutos.Na linha 18 verificamos se o que foi passado para a view é realmente uma List
Nossa action de listagem pode assumir um outro comportamento. Quando não existe nenhum produto para ser exibido ela deve retornar uma view diferente, uma view de NenhumProduto. Vejamos o teste:
[TestMethod]
public void Action_Listar_Sem_Nenhum_Produto_Deve_Retornar_View_NenhumProduto(){ repositorio .Setup(r => r.Todos()) .Returns(new List<produto>());
var viewResult = controller.Listar();
Assert.AreEqual("NenhumProduto", viewResult.ViewName);
}
</produto>
Este é um teste bastante simples também. Configuramos o repositório para retornar uma lista vazia de produtos.Na linha 8 realizamos a chamada para a action de listagem.E na linha 10 verificamos que a view retornada deve ser a view NenhumProduto, afinal o repositório não retornou nenhum produto.
Agora faremos um pequeno teste em uma action que deve listar os produtos em formato Json. Esta action recebe 2 parâmetros, mais ou menos para realizar uma paginação via ajax.Vejamos como ficou o teste:
[TestMethod]
public void Action_Obter_Deve_Retornar_Produtos_Em_Formato_Json(){
var todosProdutos = new List<produto> { new Produto("Teclado"), new Produto("Monitor") }
;
repositorio .Setup(r => r.Todos()) .Returns(todosProdutos);
var viewResult = controller.Obter(pagina: 1, quantidade: 10);
Assert.IsTrue(viewResult is JsonResult, "Deve ser um JsonResult");
var jsonResult = viewResult as JsonResult;
var jsonData = jsonResult.Data as List<produto>;
Assert.AreEqual(2, jsonData.Count);
}
</produto></produto>
Neste teste configuro o repositório para retornar uma lista de produtos. Na linha 13 fazemos a chamada para a action informando que queremos 10 resultados da página 1, ou seja, os 10 primeiros resultados vindos do repositório.Na linha 15 fazemos um assert para verificar que nossa view é na verdade um JsonResult. Fiz isso antes das conversões para obter os dados pois desta forma eu consigo saber se o teste falhará por que não é um JsonResult, caso contrário o cast daria erro e eu ficaria sem uma mensagem clara do que aconteceu.Por fim, na linha 19 verifico se o total de dados retornados para a view é 2, afinal configurei meu repositório com apenas 2 produtos.
Desta forma vimos que testar actions que retornam dados, decidem sobre quais views exibir e como os dados devem ser exibidos é relativamente simples. Vimos que uma mesma action que retorna 2 views diferentes está com seu comportamento garantido, e qualquer alteração que for feita será impactada e validada pelos testes que já existem, deixando assim a aplicação mais saudável e simples de evoluir e manter.
Os fontes podem ser baixados aqui em Zip, ou aqui no github.
Abraços, Vinicius Quaiato.