Executando testes unitários com o framework Demoiselle
Autor: Andre | Publicado: 2011-10-05T00:48:00-03:00


Primeiro, deve ser criado um projeto usando o arquétipo Vaadin do Framework Demoiselle.

Este vídeo feito pelo Cleverson (@zyc) pode ser usado como referência para a criação de uma aplicação que use o Demoiselle, com a diferença de que o arquétipo a ser utilizado é o do Vaadin.

Logo após a criação do projeto (aos 3:25 minutos do vídeo), podemos começar a modificar o mesmo.

Deve ser criado o pacote foo.init, na pasta src/main/java.

Dentro deste pacote deve ser criada a classe ApplicationLoader

package foo.init;

import javax.enterprise.context.ApplicationScoped;
import br.gov.frameworkdemoiselle.annotation.Shutdown;
import br.gov.frameworkdemoiselle.annotation.Startup;
import br.gov.frameworkdemoiselle.transaction.Transactional;

@ApplicationScoped
public class ApplicationLoader {
	
	@Startup
	@Transactional
	public void load() {
	}
	@Shutdown
	public void unload() {
	}
}

No pacote foo, dentro da pasta src/test/java, deve ser criada a classe CategoryBCTest, a qual já conta com alguns testes:

package foo;

import static org.junit.Assert.assertNotNull;

import javax.inject.Inject;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import foo.business.CategoryBC;
import foo.domain.Category;
import foo.init.ApplicationLoader;

import br.gov.frameworkdemoiselle.transaction.Transactional;
import br.gov.frameworkdemoiselle.util.DemoiselleRunner;
import static org.junit.Assert.fail;

@Transactional
@RunWith(DemoiselleRunner.class)
public class CategoryBCTest {
	
	@Inject
	private ApplicationLoader appLoader;

	@Inject
	CategoryBC bc;
	
	@Before
	public void before() {
		for (Category category : bc.findAll()) {
			bc.delete(category.getId());
		}
	}
	
	@Test
	public void testInsert() {
		Category category = getMinimalValidCategory();
		bc.insert(category);
		assertNotNull(category.getId());
	}
	
	@Test	
	public void testUpdate() {
		Category category = getMinimalValidCategory();
		bc.insert(category);
		
		bc.update(category);
		category = bc.load(category.getId());		
	}
	
	@Test	
	public void testDelete() {
		Category category = getMinimalValidCategory();
		bc.insert(category);
		category = bc.load(category.getId());	
		bc.delete(category.getId());
		category = bc.load(category.getId());
		Assert.assertNull(category);
	}
	
	@Test
	public void testInsertLogradouroNull() {
		Category category = getMinimalValidCategory();
		category.setDescription(null);
		try {
		bc.insert(category);
		}catch (javax.validation.ConstraintViolationException e) {
			return;
		}
		
		fail("Aceitou inserção sem Descrição");
	}
	
	/**
	 * Este método retorna um objeto que é minimamente válido.
	 * @return Objeto mínimo possível
	 */

	public Category getMinimalValidCategory() {		
		Category cat = new Category();
		cat.setDescription("Descrição");
		return cat;
	}

}

Ao se tentar executar o teste neste momento, é lançado o seguinte erro: java.lang.ClassFormatError: Absent Code attribute in method...

Isto ocorre porque o arquétipo disponibilzado vem com a dependência javaee-api e javaee-web-api, que especificam o JavaEE6.
No entanto, estas bibliotecas servem apenas para compilação, pois os métodos que estão dentro destes jars estão sem implementação.

Para corrigir este problema, deve ser feita a adição dos seguintes campos no arquivo pom.xml do projeto, os quais resolvem as dependências relativas a uma implementação completa do javaee 6.0:
&lt;repository&gt;
	&lt;id&gt;repository.jboss.org&lt;/id&gt;
	&lt;name&gt;JBoss Repository&lt;/name&gt;
	&lt;url&gt;http://repository.jboss.org/nexus/content/groups/public-jboss/&lt;/url&gt;
&lt;/repository&gt;

&lt;dependency&gt;
	&lt;groupId&gt;org.jboss.spec&lt;/groupId&gt;
	&lt;artifactId&gt;jboss-javaee-6.0&lt;/artifactId&gt;
	&lt;version&gt;1.0.0.Final&lt;/version&gt;
	&lt;scope&gt;test&lt;/scope&gt;
	&lt;type&gt;pom&lt;/type&gt;
&lt;/dependency&gt;

Neste ponto, o JUnit teste ainda não consegue executar o teste (é lançada uma exceção do tipo java.util.NoSuchElementException, provavelmente ligada à falta de uma fonte/conexão a um banco de dados).

Resta agora configurar o acesso ao banco de dados:

O conteúdo da pasta src/main/resources deve ser copiado para a pasta src/test/resources

Na pasta src/main/resources/META-INF
Arquivo beans.xml:

&lt;?xml version="1.0"?&gt;
&lt;beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_1.xsd"&gt;

	&lt;alternatives&gt;
		&lt;class&gt;br.gov.frameworkdemoiselle.transaction.JPATransaction&lt;/class&gt;
	&lt;/alternatives&gt;

&lt;/beans&gt;

Arquivo persistence.xml:

&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"&gt;

	&lt;persistence-unit name="bookmark-ds" transaction-type="RESOURCE_LOCAL"&gt;
		&lt;class&gt;foo.domain.Bookmark&lt;/class&gt;
		&lt;class&gt;foo.domain.Category&lt;/class&gt;
		&lt;properties&gt;
			&lt;property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver" /&gt;
			&lt;property name="javax.persistence.jdbc.user" value="sa" /&gt;
			&lt;property name="javax.persistence.jdbc.password" value="" /&gt;
			&lt;property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:hsql://localhost:9001/bookmark" /&gt;

			&lt;property name="eclipselink.logging.level" value="FINE" /&gt;
			&lt;property name="eclipselink.ddl-generation" value="create-tables" /&gt;
			&lt;property name="eclipselink.ddl-generation.output-mode" value="database" /&gt;

			&lt;property name="hibernate.show_sql" value="true" /&gt;
			&lt;property name="hibernate.format_sql" value="false" /&gt;
			&lt;property name="hibernate.hbm2ddl.auto" value="update" /&gt;
		&lt;/properties&gt;
	&lt;/persistence-unit&gt;
&lt;/persistence&gt;

Na pasta src/test/resources/META-INF
Arquivo beans.xml:

&lt;?xml version="1.0"?&gt;
&lt;beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_1.xsd"&gt;
&lt;/beans&gt;

Arquivo persistence.xml:

&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"&gt;

	&lt;persistence-unit name="bookmark-ds"&gt;
		&lt;jta-data-source&gt;java:/DefaultDS&lt;/jta-data-source&gt;
		&lt;class&gt;foo.domain.Bookmark&lt;/class&gt;
		&lt;class&gt;foo.domain.Category&lt;/class&gt;
		&lt;properties&gt;
			&lt;property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver" /&gt;
			&lt;property name="javax.persistence.jdbc.user" value="sa" /&gt;
			&lt;property name="javax.persistence.jdbc.password" value="" /&gt;
			&lt;property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:hsql://localhost:9001/bookmark" /&gt;

			&lt;property name="eclipselink.logging.level" value="FINE" /&gt;
			&lt;property name="eclipselink.ddl-generation" value="create-tables" /&gt;
			&lt;property name="eclipselink.ddl-generation.output-mode" value="database" /&gt;

			&lt;property name="hibernate.show_sql" value="true" /&gt;
			&lt;property name="hibernate.format_sql" value="false" /&gt;
			&lt;property name="hibernate.hbm2ddl.auto" value="update" /&gt;
		&lt;/properties&gt;
	&lt;/persistence-unit&gt;
&lt;/persistence&gt;

Com isto, chegamos à tão desejada barra verde do JUnit, juntamente com o deploy do projeto no JBOSS6.

Agradeço ao @mariojp pelo apoio na hora de encontrar esta solução, ao mostrar seu conhecimento sobre os arquivos de configuração.