Testando sua aplicação web Spring
Este blog deixou de ser mantido, mas o autor continua escrevendo aqui. Não deixe de assinar o novo feed!
Depois de apanhar feio, finalmente consegui criar um caso de teste no JUnit para validar o funcionamento de uma classe de serviço, cujo acesso à camada de persistência é gerenciada pelo Spring. Como é a primeira vez que eu estou criando uma aplicação web utilizando o Spring, nada mais normal do que esbarrar em algumas dificuldades.
Apesar de ter apanhado feito um cavalo, a solução é bem simples. Aqui mostro como eu fiz isso no NetBeans, porém a mesma coisa pode ser facilmente portada para outras IDEs com suporte à Ant.
Vamos ao assunto
O problema era o seguinte: Os arquivos de configuração do Spring são colocados dentro da pasta WEB-INF (ou em uma subpasta dentro desta). Então, bastava configurar o listener do Spring no web.xml para permitir que o contexto seja carregado no momento do deploy da aplicação:
-
-
<web-app>
-
<context-param>
-
<param-name>contextConfigLocation</param>
-
<param-value>/WEB-INF/spring/context-*.xml</param>
-
</context>
-
-
…
-
-
<listener>
-
<listener-class>
-
org.springframework.web.context.ContextLoaderListener
-
</listener-class>
-
</listener>
-
-
…
-
Porém, depois de codificar alguns DAOs, eu resolvi testá-los com o JUnit. Dei uma lida na documentação do Spring e vi que o Spring fornece algumas classes utilitárias para facilitar a criação de testes unitários de classes que fazem acesso a dados.
Para utilizar a classe fornecida pelo Spring, foi preciso adicionar o arquivo spring-mock.jar nas bibliotecas de teste. A classe abaixo mostra como utilizar uma classe do Spring que é própria para realização de testes que disparam alterações no banco de dados, onde, depois de executar cada caso de teste, o Spring efetua um rollback na transação, mantendo a integridade do seu banco de dados:
-
-
package br.com.tritone.blog.model.service;
-
-
import br.com.tritone.blog.model.Category;
-
import java.util.List;
-
import org.springframework.test.AbstractTransactionalSpringContextTests;
-
-
/**
-
*
-
* @author Daniel Fernandes Martins
-
*/
-
public class CategoryHibernateServiceTest extends
-
AbstractTransactionalSpringContextTests {
-
-
private CategoryService service;
-
-
-
super(testName);
-
}
-
-
public void setCategoryService(CategoryService service) {
-
this.service = service;
-
}
-
-
}
-
-
-
public void testGetCategory() {
-
-
new Category(null, "Sample category")
-
);
-
assertNotNull("The category wasn’t saved", id);
-
-
Category category = service.getCategory(id);
-
assertNotNull("The category doesn’t exists", category.getId());
-
}
-
-
public void testSaveCategory() {
-
-
new Category(null, "Sample category")
-
);
-
assertNotNull("The category wasn’t saved", id);
-
}
-
-
public void testRemoveCategory() {
-
-
Category cat = new Category(null, "Sample category");
-
service.removeCategory(cat);
-
-
try {
-
service.getCategory(id);
-
this.fail("This category must not exists");
-
}
-
// OK
-
}
-
}
-
-
public void testGetAllCategories() {
-
-
int numrec = service.getAllCategories().size();
-
-
service.saveCategory(new Category(null, "Sample category"));
-
service.saveCategory(new Category(null, "Sample category"));
-
service.saveCategory(new Category(null, "Sample category"));
-
service.saveCategory(new Category(null, "Sample category"));
-
service.saveCategory(new Category(null, "Sample category"));
-
-
List<category> list = service.getAllCategories();
-
assertEquals("Number of elements in the list isn’t expected",
-
list.size(), 5 + numrec);
-
}
-
}
-
O problema que eu estava encontrando ao fazer o teste funcionar é que os arquivos de contexto do Spring não eram encontrados dentro do classpath. Fiz inúmeras tentativas e gambiarras, nenhuma com sucesso. Mas, de repente, me deu uma luz e eu resolvi alterar o arquivo de build do NetBeans para que, depois de compilados os testes, ele copiasse os arquivos de contexto do Spring para o classpath do código de testes.
Para fazer isso temos de alterar dois arquivos. Primeiramente, abra o arquivo situado no diretório nbproject/project.properties. No final deste arquivo, adicione a seguinte linha:
-
-
web.src.dir=${web.docbase.dir}/WEB-INF
-
Finalmente, abra o arquivo build.xml, situado no diretório raíz do projeto. Insira o seguinte código dentro da tag project:
-
-
<target name="-post-compile-test"
-
depends="copy-spring-context" />
-
-
<target name="copy-spring-context">
-
<copydir src="${web.src.dir}/spring"
-
casesensitive="true"
-
dest="${build.test.classes.dir}/WEB-INF/spring"
-
/>
-
</target>
-
Ao executar o teste, o Spring injeta dentro do mesmo um objeto do tipo CategoryService via auto-wire (por tipo). Dessa forma, fica muito fácil criar testes que utilizem beans declarados no Spring. Basta declarar um método set que o Spring injeta uma instância de forma automática. Caso existam beans de tipos iguais declarados no contexto, basta que você troque o tipo de auto-wire ou retire os métodos set e recupere os objetos manualmente dentro dos seus testes, através do objeto this.applicationContext.
A cada dia que passa eu me surpreendo mais com o Spring. Êta framework porreta, esse!
Tags: dao, java, spring, testes, tutorial
