Testes de Unidade - Struts 2 - SimpleDev - Simplificando o Desenvolvimento de Software
Por Juliano Alves em 14/09/2011, atualizado em 08/10/2012
Testes são uma forma de garantir que a aplicação está funcionando corretamente, e quando é preciso alterá-la, através deles garantimos que ela vai continuar funcionando após feitas as alterações. Aqui vou mostrar como devem ser feitos os testes de unidade das actions quando trabalhamos com Struts 2.
Serão criados aqui os testes para a CarroAction, do post Simplificando - Struts 2. Primeiro, será necessário fazer uma pequena alteração na classe. O construtor da classe agora vai ter que receber o dao ao invés de criá-lo. Fica assim:
public CarroAction(final CarroDao dao) {
E para fazer os testes, serão adicionados ao build.gradle os jars do JUnit e do Mockito:
Abaixo, a classe de testes. Vou explicar todos os passos, caso o leitor não tenha conhecimento sobre JUnit ou sobre mocks.
Primeiro é criada uma instancia de CarroAction, a qual será testada. Repare que somente essa classe deve ser testada, não precisamos que o dao efetivamente salve os objetos passados para ele onde quer que seja, mas precisamos que ele simule esse comportamento, por isso será criado um mock de CarroDao. Um mock é um objeto que simula o comportamento de um objeto real (nessa caso, do CarroDao), que vai se comportar da forma que nós determinarmos – isso será mostrado à seguir.
O método setUp é anotado com @Before, uma anotação do JUnit que indica que esse método deve ser chamado antes de cada teste. MockitoAnnotations.initMocks(this) inicializa as classes anotadas com @Mock, e isso feito, criamos uma nova action, passando o dao mockado.
Cada método anotado com @Test será um teste para o JUnit. Assim com o nome diz, nosso primeiro teste vai listar todos os carros (lembrando que nomes significativos são muito importantes!), e é aqui que devemos dizer para o dao como ele deve se comportar:
when(dao.lista()).thenReturn(Collections.singletonList(new Carro(1L, "Camaro", 2012)));
O Mockito tem uma interface fluente que facilita muita a configuração dos mocks. Aqui instruímos nosso dao mockado da seguinte maneira: "quando seu método lista for chamado, retorne essa lista com um carro só", assim conseguimos simular uma busca no banco de dados. Em um banco de dados real existem inúmeros registros, mas repare que não precisamos de mais do que um para o teste, ele só precisa retornar uma quantidade de dados suficientes para que nossa action possa trabalhar com eles. Se a action deve trazer uma lista de carros, uma lista contendo um carro é o suficiente.
O método lista retorna uma String, mas não a testei porque ela é para uso do Struts 2, e como sempre retorno "ok", não achei necessário. Caso o método possa retornar diferentes Strings, deve ser criado um teste considerando isso.
Através do método getCarros obtemos a lista de carros, tal qual a jsp faria, e então usamos o método assertFalse da classe Assert, mostrando que o que é esperado como resultado do teste é que a lista não esteja vazia.
O segundo teste verifica se a action adiciona um novo carro sem que haja erros. Usando o método setCarro é informado para a action qual carro deve ser adicionado, e em seguida é chamado o método adiciona para efetuar essa ação. Esse teste não possui um assert, isso porque não há como verificar se o Carro foi adicionado – só é verificado que não ocorre nenhum erro durante esse processo. Ele também é bastante simples porque não há lógica no método adiciona, o Carro apenas é passado para o dao, mas poderia haver alguma lógica que lida com os dados do carro, como uma validação por exemplo. Nesse caso, seria necessário mais um teste, em que é considerada essa situação.
Um ponto importante foi a alteração no construtor da classe CarroAction, pois sem ela, não seria possível prover um mock do dao, tornando a classe intestável. Para tal, foi necessário injetar a dependência, para possibilitar o teste de unidade. Mais uma vantagem de criar testes: melhorar o design das classes!
É responsabilidade do desenvolvedor garantir que o código que ele produz seja de qualidade, caso você não o faça, está tomando uma atitude amadora, além de estar possivelmente produzindo bugs. Pode parecer que escrever testes aumenta o trabalho e o tempo de desenvolvimento (no começo, realmente é necessário mais tempo), mas eu diria que diminui – e muito – o retrabalho, além de trazer as outras vantagens já citadas. Tente!