Testes de Classes DAO

Olá.
Entrei recentemente em um estágio e estou aprendendo ainda a usar JEE, assim como outras ferramentas que eu nunca havia usado. Sou bastante iniciante ainda.

A Minha dúvida acredito ser simples. O Projeto em que eu trabalho usa JPA, Maven e JBoss. Preciso fazer testes com JUnit em classes DAO, ou seja classes que acessam o BD via EntityManager. Para isso, preciso criar um EntityManager.
Como eu posso fazer isso? É possível testar independente do JBoss (que acessa o BD)? Li que posso usar o EntityManagerFactory, mas ocorre erro na Criação dele. Algum problema de configuração?

Obrigado

Posta o erro para que possamos te ajudar.

Oi nelsonmlneto

Imagino que tu estejas usando uma IDE (vou supor que seja Eclipse) e que tu que queiras rodar os testes de DAO de dentro da IDE. Vou supor que tua estrutura de diretorios seja:

Project/src – fontes com DAO
Project/tst – testes

Outra coisa, vou supor que tu tenhas os parametros de acesso ao DB, isto eh, que tu saibas como criar a conexao usando persistence.xml.

A primeira coisa eh garantir que todos os fontes estao sendo compilados no mesmo diretorio (o padrao do eclipse eh compilar em diretorios separados, conforme os diretorios que tu configura como fontes). Eu anexei uma imagem de como deve ficar a tua configuracao.

A configuracao anterior eh absolutamente necessaria, caso contrario o EntityManager nao vai encontrar as entidades (tu teras que limpar o binarios e forcar uma recompilacao para que esta configuracao entre em vigor). A proxima etapa eh criar o META-INF diretorio dentro do diretorio de testes:

Project/tst/META-INF

Dentro deste diretorio tu precisas colocar o arquivo persistence.xml com todas as configuracoes necessarias para se conectar ao banco de dados:

Project/META-INF/persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Persistence deployment descriptor for dev profile -->
<persistence 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_1_0.xsd"
	version="1.0">
	<!-- 
	ATENCAO:
	Este arquivo eh usado *SOMENTE* em testes unitarios e serah *IGNORADO* quando feito deploy no servidor de aplicacao
	 -->
	<persistence-unit name="my-pu">	
		<provider>org.hibernate.ejb.HibernatePersistence</provider>
		<properties>
			<property name="hibernate.connection.driver_class" value="org.postgresql.Driver" />
			<property name="hibernate.connection.username" value="pq-user" />
			<property name="hibernate.connection.password" value="pg-pass" />
			<property name="hibernate.connection.url" value="jdbc:postgresql://127.0.0.1:5432/my-db" />
		</properties>
	</persistence-unit>
</persistence>

O arquivo acima se refere a PostgreSQL entao adapte as tuas necessidades (isto deve estar em algum outro arquivo de configuracao, ou mesmo um persistence.xml)

Agora a parte de criacao do EntityManager (estou colocando um exemplo de estrutura de testes):

public class MyDAOTest {

	private static final String PERSISTENCE_UNIT_NAME = "my-pu";
	private static Logger log = Logger.getAnonymousLogger();
	static EntityManager em = null;
	private static long start = 0L;
	private static boolean isEmOk = false;
	
	private FatCompetenciaDAO dao = null;
		
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {

		EntityManagerFactory emf = null;
		
		start = System.currentTimeMillis();
		try {
			log.info("Creating EntityManager");
			emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
			em = emf.createEntityManager();			
			log.info("EntityManager created successfully");
			isEmOk = true;
		} catch (Exception e) {
			log.severe("Error creating EntityManager: " + e + "\n" + Arrays.toString(e.getStackTrace()));			
			isEmOk = false;
		}
	}

	@AfterClass
	public static void tearDownAfterClass() throws Exception {

		long duration = 0L;
		
		if (isEmOk) {
			em.close();			
		}
		duration = System.currentTimeMillis() - start;
		log.info("Test duration: " + (duration / 1000) + " secs (" + duration + " milisecs)");
	}

	@Before
	public void setUp() throws Exception {
		
		if (isEmOk) {
			this.dao = new MyDAO() {
				
				@Override
				protected EntityManager getEntityManager() {

					return em;
				}
			};	
			log.info("EntityManager Transation begin");
			em.getTransaction().begin();			
		}
	}

	@After
	public void tearDown() throws Exception {

		if (isEmOk) {
			em.getTransaction().rollback();
			log.info("EntityManager Transation rollback");
		}
		this.dao = null;
	}		

	@Test
	public void testAcesso() {

		if (isEmOk) {
                     // corpo do teste
		}
	}
}

Acho que era isso que eu teria para contribuir. Se tiveres alguma duvida, por favor.