Problema ao injetar DAO no teste unitário

35 views
Skip to first unread message

Gregory Zanelato

unread,
Jul 27, 2016, 2:04:54 PM7/27/16
to caelum-vraptor
Boa tarde pessoal.

Estou usando VRaptor4 + Wildfly + JPA (eclipselink).

No meu DAO, a injeção de dependência do EntityManager está da seguinte maneira:

@PersistenceContext

private EntityManager em;


Funciona perfeitamente.

Porém, não consigo fazer um teste unitário para testar esse DAO. Utilizando Mockito + JUnit.

Alguém tem algum exemplo de como posso injetar esse DAO no meu teste?

Testei de diversas maneiras, até programaticamente:

WeldContainer   weld = new Weld().initialize();

ServicesDAO dao = weld.instance().select(ServicesDAO.class).get();


Ou mesmo com

@Inject

O DAO é instanciado, porém o entitymanager está null.

Obrigado.

[]s

Raphael Almeida

unread,
Jul 27, 2016, 3:17:30 PM7/27/16
to caelum-...@googlegroups.com

Boa tarde Gregory,

A princípio vc deve mockar a dependência do DAO o entitymanager (http://www.adam-bien.com/roller/abien/entry/mocking_jpa_entitymanager_with_query).

Abs


--
Você recebeu essa mensagem porque está inscrito no grupo "caelum-vraptor" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para caelum-vrapto...@googlegroups.com.
Para postar nesse grupo, envie um e-mail para caelum-...@googlegroups.com.
Acesse esse grupo em https://groups.google.com/group/caelum-vraptor.
Para mais opções, acesse https://groups.google.com/d/optout.

Rafael Ponte

unread,
Jul 27, 2016, 3:27:54 PM7/27/16
to caelum-...@googlegroups.com
Olá,

Não é recomendado mockar a EntityManager/Session de um DAO, pois a única responsabilidade de um DAO é conversar com o banco de dados. Se você mockar essa responsabilidade você está fingindo esse comportamento, logo seu teste não servirá de nada.

Nesse caso você precisa de fato "tocar" no banco de dados para validar sua consulta SQL, constraints, INSERTs etc.

Um abraço,
--
Rafael Ponte
TriadWorks | Formação Java
http://cursos.triadworks.com.br

Raphael Almeida

unread,
Jul 27, 2016, 4:22:38 PM7/27/16
to caelum-...@googlegroups.com

Boa tarde Rafael Ponte,

Eu concordo contigo, eu disse "a princípio"  por não saber exatamente o objetivo do teste unitário do Gregory.

Aqui tb tem um exemplo de mock de entitymanager onde fez sentido para o autor: https://github.com/caelum/vraptor-jpa/blob/master/src/test/java/br/com/caelum/vraptor/jpa/EntityManagerCreatorTest.java

Agora pensando em tocar o banco e etc vejo como teste de integração, logo faz sentido validar as consultas.

No geral, eu testo o domínio do negócio com unitário, mockando o q for necessário, depende do desacoplamento de domínios. Quando o domínio interage com elementos de entrada ou saída, (controller, daos e etc), geralmente vejo a necessidade de testes de integração.

Gregory, se sua dúvida for mais conceitual há uma lista de discussão que trata disso: tdd-no-m...@googlegroups.com

Abs

Rafael Ponte

unread,
Jul 27, 2016, 6:34:24 PM7/27/16
to caelum-...@googlegroups.com
Oi Raphael,

Sim, nesse casos seria um teste de integração. 

Sobre o exemplo que você citou, ele está mais interessado em testar as chamadas da API do que o acesso ao banco, por esse motivo faz sentido mockar.
 
Quando testamos um DAO não tem muito para onde correr na maioria das vezes quando lidamos com banco de dados, precisamos validar a execução, processamento e retorno de um SQL. A única maneira é acessando o banco de dados.

Um abraço,

Gregory Zanelato

unread,
Jul 28, 2016, 7:07:31 AM7/28/16
to caelum-vraptor
Bom dia !

Sim, na verdade eu não queria mockar, gostaria de validar mesmo o acesso ao banco e as queries, pra ser mais fiel possível. Por isso queria um jeito de injetar o EntityManager do meu DAO.

[]s

Você recebeu essa mensagem porque está inscrito em um tópico no grupo "caelum-vraptor" dos Grupos do Google.
Para cancelar inscrição nesse tópico, acesse https://groups.google.com/d/topic/caelum-vraptor/HS5nXBtpeNU/unsubscribe.
Para cancelar inscrição nesse grupo e todos os seus tópicos, envie um e-mail para caelum-vrapto...@googlegroups.com.

Para postar nesse grupo, envie um e-mail para caelum-...@googlegroups.com.
Acesse esse grupo em https://groups.google.com/group/caelum-vraptor.
Para mais opções, acesse https://groups.google.com/d/optout.



--
Gregory Petterson Zanelato

Raphael Almeida

unread,
Jul 28, 2016, 11:39:04 PM7/28/16
to caelum-...@googlegroups.com

Fala Ponte,

Concordo contigo, queria até saber do teu feeling dum dado contexto, onde o projeto segue a ideia da arquitetura hexagonal/cebola, o domínio fica mto fácil de testar por unitário, enquanto nas outras camadas acaba sendo comum usar teste de integração ou até teste de tela/aceitação.

Claro que não dá pra generalizar, mas eu fico com essa sensação, onde o ato de testar traz resultados efetivos.

*Mal ae sair do foco da thread*

Abs

Rafael Ponte

unread,
Jul 28, 2016, 11:52:20 PM7/28/16
to caelum-...@googlegroups.com
Oi Raphael,

Sendo bem sincero, eu evito escrever testes de aceitação pelo fato de serem mais caros, frágeis e normalmente de dificil manutenção. No geral deixo eles para fluxos de negócio realmente importantes. Costumo cobrir o código com teste de unidade (entidades, lógicas de negócio, geração de json/xml etc) e integração (persistência, disco, web services etc). Como as aplicações que trabalho usam Spring, eu tiro proveito do módulo Spring Testing para os testes de integração (mas dá para testar sem ele). 

Que dificuldades você está tendo?

Um abraço,

Gregory Zanelato

unread,
Jul 29, 2016, 8:42:33 AM7/29/16
to caelum-vraptor
Boa dia Srs.

Alguém tem um exemplo ou já passou por minha situação?

Injetar um DAO que usar @PersistenceContext no teste unitário? (fazer o papel do Wildfly)

[]s

Você recebeu essa mensagem porque está inscrito em um tópico no grupo "caelum-vraptor" dos Grupos do Google.
Para cancelar inscrição nesse tópico, acesse https://groups.google.com/d/topic/caelum-vraptor/HS5nXBtpeNU/unsubscribe.
Para cancelar inscrição nesse grupo e todos os seus tópicos, envie um e-mail para caelum-vrapto...@googlegroups.com.

Para postar nesse grupo, envie um e-mail para caelum-...@googlegroups.com.
Acesse esse grupo em https://groups.google.com/group/caelum-vraptor.
Para mais opções, acesse https://groups.google.com/d/optout.



--
Gregory Petterson Zanelato

Rafael Ponte

unread,
Jul 29, 2016, 8:56:13 AM7/29/16
to caelum-vraptor
Oi Gregory,

Dependendo de como você rode/escreva seus testes a DI pode não funcionar. Como você está rodando os testes?


Gregory Zanelato

unread,
Jul 29, 2016, 9:26:31 AM7/29/16
to caelum-vraptor
Oi Rafael.

É, talvez não dê mesmo.

Vou descrever meu cenário:

Implementei um DAO da seguinte maneira:

public class ServicesDAO {


        @PersistenceContext

        private EntityManager em;
     

        public List<Categoria> getCategorias() throws RuntimeException {

               return em.createNamedQuery("Categoria.findAll", Categoria.class).getResultList();
                }
...


Ele funciona perfeitamente, o Wildfly Injeta nele o em.

Dai queria construir um teste unitário para por ex: testar esse método getCategorias. Testar real, acessando o banco mesmo.

Queria fazer algo do tipo em meu teste unitário:


@Inject
ServicesDAO dao;


    @Test

    public void getCategorias(){

            Assert.assertTrue(servicesDAO.getCategorias().size() > 0);

        }



O injeção até funciona, mas meu EntityManager do DAO está null.


Alguma observação ou sugestão?

[]s

Rafael Ponte

unread,
Jul 29, 2016, 10:04:56 AM7/29/16
to caelum-vraptor
Olá,

Existem ferramentas que podem te ajudar, como o plugin do VRaptor ou Arquillian ou mesmo Spring Testing. De qualquer forma, você pode fazer do jeito mais simples mesmo, algo como:

@Test
public void deveBuscarProdutoPorId() {

  EntityManager entityManager = new JpaUtil().getEntityManager(); // melhor se for banco/schema de testes
  ProdutoDao dao = new ProdutoDao(entityManager);

  int id = 2020;
  Produto produto = dao.busca(id);

  assertNotNull(produto);
  assertEquals("iPad", produto.getNome());
}

Repare que estou criando a EntityManager dentro do teste e injetando no DAO via construtor. Ou seja, estou fazendo na mão o que frameworks fazem de graça para mim.

Um abraço,

Raphael Almeida

unread,
Jul 29, 2016, 10:32:54 AM7/29/16
to caelum-...@googlegroups.com
Bom dia Rafael,

É mais curiosidade mesmo, eu vi que varias das suas ideias vão ao encontro das minhas, eu acho que projetos maduros e bem estruturados acabam tendendo a isso.

Valeu!

Em 29 de julho de 2016 00:52, Rafael Ponte <rpo...@gmail.com> escreveu:

Rafael Ponte

unread,
Jul 29, 2016, 10:50:23 AM7/29/16
to caelum-...@googlegroups.com
Opa,

Quando não se tem um Spring Testing da vida para nos auxiliar temos que partir para forma básica mesmo. Sabendo estruturar os testes e classes utilitários você consegue manter uma boa qualidade e manutenção dos teus testes. Recomendo você dar uma olhada no jUnit Rules para seus testes de integração, seja para iniciar/comitar/rollback as transações, abrir/fechar conexões, injetar EntityManager nos DAOs ou mesmo limpar/popular o banco de dados.

Um abraço,

Clairton Rodrigo Heinzen

unread,
Jul 29, 2016, 1:05:51 PM7/29/16
to caelum-vraptor
Boa Tarde Gegory

Posso estar enganado, mas o @PersistenceContext não vai funcionar somente com o CDI(Weld) mas dentro do Wildfly vai funcionar  porque tem todo o JavaEE.
Uma saída seria criar um @Produces que retorna o EntityManager e injeta-lo com @Inject.
Outra saída seria criar o EntityManager na mão e instanciar o DAO na mão passando também passando o EntityManager no construtor.

Atenciosamente
Clairton

Gregory Zanelato

unread,
Aug 1, 2016, 8:15:09 AM8/1/16
to caelum-vraptor
Bom dia Srs.

Pois é, eu não queria instanciar o EntityManager e passar no construtor pro DAO, pois teria de mexer em todos os meus DAOs. Mas com certeza funciona.
Eu dei uma olhada nesse cara:
 

Acreditei que ele faria isso pra mim, emularia CDI(Weld) para injetar o @PersistenceContext.

Mas não consegui fazer funcionar.

De qualquer forma, obrigado a todos pela atenção!

[]s

--
Você recebeu essa mensagem porque está inscrito em um tópico no grupo "caelum-vraptor" dos Grupos do Google.
Para cancelar inscrição nesse tópico, acesse https://groups.google.com/d/topic/caelum-vraptor/HS5nXBtpeNU/unsubscribe.
Para cancelar inscrição nesse grupo e todos os seus tópicos, envie um e-mail para caelum-vrapto...@googlegroups.com.
Para postar nesse grupo, envie um e-mail para caelum-...@googlegroups.com.
Acesse esse grupo em https://groups.google.com/group/caelum-vraptor.
Para mais opções, acesse https://groups.google.com/d/optout.



--
Gregory Petterson Zanelato

Rafael Ponte

unread,
Aug 1, 2016, 8:33:58 AM8/1/16
to caelum-vraptor
Oi,

Você pode fazer a DI via reflections caso não queria mudar seus DAOs. No final das contas, é o que o framework faz por debaixo dos panos.

Um abraço,

Você recebeu essa mensagem porque está inscrito no grupo "caelum-vraptor" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para caelum-vrapto...@googlegroups.com.

Para postar nesse grupo, envie um e-mail para caelum-...@googlegroups.com.
Acesse esse grupo em https://groups.google.com/group/caelum-vraptor.
Para mais opções, acesse https://groups.google.com/d/optout.
--

Clairton

unread,
Aug 1, 2016, 9:29:14 AM8/1/16
to caelum-...@googlegroups.com
Bom Dia.
Acho que @PersistenceContext depende de outra especificação, se não me engano do EJB.


Atenciosamente
Clairton Rodrigo Heinzen

Rafael Ponte

unread,
Aug 1, 2016, 9:37:12 AM8/1/16
to caelum-...@googlegroups.com
Opa,

Para não ter que fazer reflections na mão, recomendo usar o framework Mirror. Daí bastaria fazer algo como abaixo:

ProdutoDao dao new  ProdutoDao();
EntityManager em = new JpaUtil().getEntityManager();

new Mirror().on(dao).set().field("entityManager").withValue(em);

Acha que ajuda?

Um abraço,

--
Você recebeu essa mensagem porque está inscrito no grupo "caelum-vraptor" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para caelum-vrapto...@googlegroups.com.

Para postar nesse grupo, envie um e-mail para caelum-...@googlegroups.com.
Acesse esse grupo em https://groups.google.com/group/caelum-vraptor.
Para mais opções, acesse https://groups.google.com/d/optout.
--

Gregory Zanelato

unread,
Aug 1, 2016, 12:14:05 PM8/1/16
to caelum-vraptor
Boa Rafael!

Fiz com reflection mesmo, assim não mexo em nada no meu DAO.
E o EntityManager na mão mesmo.


Obrigado a todos!

[]s

Você recebeu essa mensagem porque está inscrito em um tópico no grupo "caelum-vraptor" dos Grupos do Google.
Para cancelar inscrição nesse tópico, acesse https://groups.google.com/d/topic/caelum-vraptor/HS5nXBtpeNU/unsubscribe.
Para cancelar inscrição nesse grupo e todos os seus tópicos, envie um e-mail para caelum-vrapto...@googlegroups.com.

Para postar nesse grupo, envie um e-mail para caelum-...@googlegroups.com.
Acesse esse grupo em https://groups.google.com/group/caelum-vraptor.
Para mais opções, acesse https://groups.google.com/d/optout.



--
Gregory Petterson Zanelato
Reply all
Reply to author
Forward
0 new messages