Como testar meu DAO?

Estou começando um projeto e gostaria de aplicar TDD.

Dentro do meu modelo, consigo testar tranquilamente com JUnit, mas quando chego no meu DAO não sei como testar.

Como posso fazer para testar os métodos do meu DAO?
Por exemplo, tenho um método específico que vai buscar todos as entidades que foram criadas nos últimos 10 dias. Gostaria de testar este método.

Dei uma olhada no HibernateMock, ele é realmente a melhor opção? Existem outras opções?

É simples: você só deve ter dados de mentirinha que correspondam a sua regra, assim você vai conferindo se eles estão sendo retornado pelos métodos do DAO.

Por exemplo, eu não faço mais isso, mas antes eu constumava fazer algo do tipo:

String nome = "JAUM";
Pessoa pessoa = new Pessoa(nome);
dao.save(pessoa);
assertEquals(dao.buscaPorNome(nome).get(0).getNome(), nome);

hard coded mesmo, era chato para métodos mais específicos, como esse seu.

Agora sobre o Hibernate mock, eu também gostaria de saber, por isso estou respondendo #up.

OBS: Com TDD você escreve teste antes de qq código (só não sei se o pessoal faz isso na prática e tals)

Aqui usamos hsqldb ou entao o mysql mesmo com rollback ao final do teste.
No caso so hsqldb ele cria toda a estrutura do banco usando hibernate.
Depois disso inserimos alguns valores no banco e finalmente executamos uma busca.

Algo do tipo:

List<Entidade> listaDeEntidadesUltimos10Dias = entidadesDAO.buscaEntidadesCriadasUltimos10Dias();
assertNotNull(listaDeEntidadesUltimos10Dias);
assertEquals(15, listaDeEntidadesUltimos10Dias.size());
for(Entidade entidade : listaDeEntidadesUltimos10Dias){
  assertTrue( entidade.getDataCriacao().before("amanha") );
  assertTrue( entidade.getDataCriacao().after("dez_dias_atras") );
}

Apenas para dar uma ideia do que voce pode testar e em que direcao voce pode ir.
Boa sorte! :thumbup:

Cara,

Eu costumo testar DAOs usando o DBUnit. Com ele, você garante que seu banco de dados de teste estará sempre em um estado conhecido na hora de executar os testes, e você não precisa ficar se preocupando em dar rollback no final dos testes.

Nao sou muito fa do DBUnit, odeio ter que ficar criando uma porrada de XML.

Voce pode garantir o mesmo com HSQLDB - e sem a porrada de XML.
Na verdade o DBUnit usa HSQLDB e alimenta o banco atraves dos arquivos XML, nos fazemos isso via codigo.
Foi o que eu entendi do “GetStarted” do DBUnit ( li a alguns anos atras bem por cima, nao tenho 100% de certeza. :slight_smile: )

Pra deixar claro, executamos “rollback” apenas quando testamos contra mysql. :wink:

Eu uso o Hibernate com uma propriedade no arquivo de configuração para limpar o banco toda vez que criar uma nova session factory. Então, no @BeforeClass ou @Before de cada teste crio uma nova session factory. Para garantir que o banco estará limpo e os testes consistentes. Então, faço a inserção dos dados via código semelhante a maneira que o keller mencionou.

[quote=keller][quote=pango]
Cara,
Eu costumo testar DAOs usando o DBUnit.
[/quote]
Nao sou muito fa do DBUnit, odeio ter que ficar criando uma porrada de XML.

Voce pode garantir o mesmo com HSQLDB - e sem a porrada de XML.
Na verdade o DBUnit usa HSQLDB e alimenta o banco atraves dos arquivos XML, nos fazemos isso via codigo.
Foi o que eu entendi do “GetStarted” do DBUnit ( li a alguns anos atras bem por cima, nao tenho 100% de certeza. :slight_smile: )

Pra deixar claro, executamos “rollback” apenas quando testamos contra mysql. :wink:
[/quote]

Keller,

Você tem razão no que diz, mas eu acho que você consegue uma legibilidade muito maior do estado do banco de dados olhando um XML do que olhando uma pancada de linhas de código com statements.

Ah, e você pode usar o DBUnit com qualquer banco, não somente o HSQLDB. :wink:

Segue minha observação…
Cuidado ao usar testes em bancos de dados quando for fazer TDD, principalmente se for teste de unidade… imagine vc roda um junit e esquece que esta apontando para a base de produção e simplesmente ele insere, apaga, altera um dado de produção…
Eu não costumo usar testes de dados de bancosdedados, pois não faz sentido para mim. principalmente se tiver usando um framework de persistência como hibernate, se quiser testar baixe o código do framework e execute o testes do próprio framework e não crie um na sua aplicação.
Lembrando que muita gente usa Teste unitarios de um jeito errado(testa select, dados, coisas sem logica, criação de arquivos…) quando vc poderia fazer o mesmo simplesmente com um objeto fake(‘Mock’) e + uma ponto de teste de unidade(JUnit,…) é q nunca deve fazer chamada externas (IO, Banco de Dados … )

Valeu pelas respostas, vou dar uma olhada em como testar com hsql. E com HibernateMock, alguém já teve experiência com ele?

[quote=Priuli]Segue minha observação…
Cuidado ao usar testes em bancos de dados quando for fazer TDD, principalmente se for teste de unidade… imagine vc roda um junit e esquece que esta apontando para a base de produção e simplesmente ele insere, apaga, altera um dado de produção…
Eu não costumo usar testes de dados de bancosdedados, pois não faz sentido para mim. principalmente se tiver usando um framework de persistência como hibernate, se quiser testar baixe o código do framework e execute o testes do próprio framework e não crie um na sua aplicação.
Lembrando que muita gente usa TDD de um jeito errado(testa select, dados, coisas sem logica, criação de arquivos…) quando vc poderia fazer o mesmo simplesmente com um objeto fake(‘Mock’) e + uma ponto de teste de unidade(JUnit,…) é q nunca deve fazer chamada externas (IO, Banco de Dados … )[/quote]

Eu não estou testando inserts ou findByIds da vida…são métodos específicos da aplicação que buscam dados para uma determinada regra de negócio, como por exemplo as entidades criadas nos 10 últimos dias.

Priuli,

Discordo de você. Eu acho que devemos, sim, testar se nosso método está retornando corretamente os clientes cadastrados em uma certa data, ou se o arquivo que estamos gerando está seguindo o leiaute especificado.

Para testar código relacionado a Banco de Dados eu uso o DBUnit, como disse. Já para testar geração de arquivos, eu costumo fazer o seguinte: usando o FileUtils da commons-io, comparo o conteúdo do arquivo gerado pela minha aplicação com o de outro arquivo que criei “na mão”.

Pode parecer um pouco trabalhoso, mas você não imagina a quantidade de bugs que já peguei desta forma…

[quote=pango]

Priuli,

Discordo de você. Eu acho que devemos, sim, testar se nosso método está retornando corretamente os clientes cadastrados em uma certa data, ou se o arquivo que estamos gerando está seguindo o leiaute especificado.

Para testar código relacionado a Banco de Dados eu uso o DBUnit, como disse. Já para testar geração de arquivos, eu costumo fazer o seguinte: usando o FileUtils da commons-io, comparo o conteúdo do arquivo gerado pela minha aplicação com o de outro arquivo que criei “na mão”.

Pode parecer um pouco trabalhoso, mas você não imagina a quantidade de bugs que já peguei desta forma…[/quote]

Existem diversas ferramentas para testes e tipos de testes diferentes o que eu escrevi foi de ñ usar chamada IO em teste de unidade das suas classes java(JUnit)… se vc criar em outra estrutura(DBUnit) fora do JUnit é diferente e até aceito, pois em alguns momentos precisamos testar outras ações, integrações… mas para a maioria das situações eu ñ preciso fazer pois eu consigo testar(individualmente) 100% das minhas classes com teste de unidade sem realizar chamadas de e/s(io). Segue um exemplo dado por vc: naqueles arquivos que tem layout eu testo o layout(texto do arquivo) e não testo a escrita(em disco) do arquivo em si, eu trabalho o design das classes para que eu consiga testar tudo antes da chamada externa(IO), esta forma de teste requer bastante uso de refactoring durante e após a implementação da classe a ser testada e do teste. a diferença que eu consigo prever muitas coisas sem chamadas externas que agiliza os testes!!

[quote=Nykolas Lima]Valeu pelas respostas, vou dar uma olhada em como testar com hsql. E com HibernateMock, alguém já teve experiência com ele?

Eu não estou testando inserts ou findByIds da vida…são métodos específicos da aplicação que buscam dados para uma determinada regra de negócio, como por exemplo as entidades criadas nos 10 últimos dias.[/quote]

ñ disse que estava, queria so deixa meu ponto de vista a todos.
O legal dos testes é q quanto mais vc usa mais vc consegue perceber o que poderia melhorar e aplicar no teste, ñ importa a forma que vc vai fazer sempre tem vantagem contra os bugs, o que é possivel fazer é melhorar a qualidade,simplicidade e segurança de executar seus testes e suas classes que serãotestadas.

Voce nao deveria nem pensar em uma situacao dessas, isso nao deve existir de maneira alguma.

Faz sentido testar pois voce tera operacoes em cascada para update/delete e integridades para inserts.
Voce pode testar se seu mapeamento esta correto e se as cascadas estao de acordo com suas expectativas.

Quanto a select’s imagine a situacao aonde voce tem que buscar as atividades dessa semana,
voce pode testar se a data da atividade esta dentro da semana. :wink:

TDD e’ uma metodologia: red -> green -> refactor - e nao diz nada sobre o que voce testa ou como testa.

Uhmn… aceita DBUnit mas nao JUnit?

E como ja tinha sido citado acima.

magia negra total, refactoring antes mesmo do codigo! estou impressionado!
tem uma galera do GUJ que apavora total! High5!

Seguindo as colocações do Keller, eu ñ costumo utilizar o DBUnit pois ñ sou muito a favor. eu sou a favor do uso do JUnit e ñ sou muito fã do dbunit mas ñ to dizendo q nunca vou usar ou q alguém ñ deva usar e sim que eu evito de usar o dbunit. Já o junit eu uso sempre
Sobre a Magia Negra rs queria dizer que durante e após a implementação das classes(lógica) e dos testes sempre faço refactor a fim de retirar o acoplamento, estruturando minhas classes para que eu consiga testar tudo sem chamadas de e/s… Explicando já que o Ke. levou ao pé dá letra, sem nenhum o bom senso e sim TDD é uma metodologia e pode aplicar de vários formas, eu aborto muito no conceito de teste de unidade(que deveria ter citado no texto e ñ ter colocado como TDD com escrevi, passou despercebido) e cabo sempre argumentando neste sentido + claro, temos varias abordagem anyway…

bola de cristal total!, estou impressionado! tem uma galera do GUJ que apavora total! High5!

Pelo contrario vc tem pensar para que isso nunca aconteça e assegurar que ñ ocorrera, já tive colegas que tiveram problemas com isso eram estagiarios mas se enganaram, comum no ser humano!!

:lol:

Hahaha, agora faz algum sentido…

Caramba, voce e’ um assassino da lingua Portuguesa! Eu que aborto essa thread!

Depois reclamam que no GUJ nao tem mais discussoes de nivel.
Nem escrever o pessoal nao sabe mais, desisto! 8)

[quote=keller]Caramba, voce e’ um assassino da lingua Portuguesa! Eu que aborto essa thread!
[/quote]

Vou escrever formalmente nas próximas vezes que você estiver no tópico, vou até pedir para meu advogado ajudar a escrever bonitinho pra vc!! lol rss :lol:

kkkk

Cara, testar contra o banco de dados que esta rodando o sistema em producao e’ fora de cogitacao.
Voce nao deve nem pensar em uma situacao dessas, nenhum de seus testes deve jamais apontar pra producao.

Diz isso pra um estagiário e junior que tive aqui, tem pessoas que vivem viajando e consegue façanhas incríveis. Eu prefiro evitar chamadas externas nos testes, eu sei q eu ñ cometo tal erro + ñ posso assegurar a todos da equipe. Eu tomei esta regra como base logo apos ter q trabalhar em um sistema antigo,( q ñ participei no inicio), lá os testes faziam varias coisas no banco(inserir,deletar,select)e o que apontava para o banco era um arquivo de configuração q ñ sei pq sempre tava apontando para produção, eu descobri logo a analisar o sistema e a equipe tava fazendo testes na produção a uma cara e nem se tocaram, só apenas quando eu fui falar, sorte minha q hj que a equipe foi reformulada.

  • basta usar direito(pensar) q ñ ocorre estas bizarrices, mas por estas e outras eu evito mas c ñ tiver jeito ai é mão na massa.