Eu tenho um método DAO que utiliza o Spring para acesso JDBC. Ele calcula a taxa de sucesso de um vendedor em vender um item.
Aqui está o código:
public BigDecimal getSellingSuccessRate(long seller_id) {
String sql = "SELECT SUM(IF(sold_price IS NOT NULL, 1, 0))/SUM(1)
FROM transaction WHERE seller_id = ?";
Object[] args = {seller_id};
return getJdbcTemplate().queryForObject(sql, args, BigDecimal.class);
}
Como devo testar esse método ou qualquer método DAO com JUnit? Quais são algumas das práticas recomendadas para testar a lógica de acesso a dados? Estou pensando em testá-lo em um banco de dados incorporável carregado com alguns dados, mas não deveríamos fazer testes de integração semelhantes a um ambiente de produção em termos de RDBMS e o esquema?
java
programming-practices
testing
tdd
Michael
fonte
fonte
Respostas:
O problema com o uso de um banco de dados 'real' para teste de unidade é a configuração, remoção e isolamento dos testes. Você não precisa criar um banco de dados MySQL totalmente novo e criar tabelas e dados apenas para um teste de unidade. Os problemas com isso estão relacionados à natureza externa do banco de dados e seu banco de dados de teste está inoperante, seus testes de unidade falham. Também há problemas em garantir que você tenha um banco de dados exclusivo para teste. Eles podem ser superados, mas há uma resposta mais simples.
Zombar do banco de dados é uma opção, no entanto ele não testa as consultas reais executadas. Ele pode ser usado como uma solução muito mais simples quando você deseja garantir que os dados do DAO passem pelo sistema corretamente. Mas, para testar o próprio DAO, você precisa que algo por trás do DAO tenha os dados e as consultas sejam executadas corretamente.
A primeira coisa a fazer é usar um banco de dados em memória. O HyperSQL é uma excelente opção para isso, pois tem a capacidade de emular o dialeto de outro banco de dados - para que as pequenas diferenças entre os bancos de dados permaneçam as mesmas (tipos de dados, funções e similares). O hsqldb também possui alguns recursos interessantes para teste de unidade.
Isso carrega o estado do banco de dados (as tabelas, dados iniciais) do
testData
arquivo.shutdown=true
desligará automaticamente o banco de dados quando a última conexão for fechada.Usando a injeção de dependência , faça com que os testes de unidade selecionem um banco de dados diferente daquele utilizado pela produção (ou teste ou local).
Seu DAO usa o banco de dados injetado para o qual você pode iniciar testes no banco de dados.
Os testes de unidade serão parecidos com (um monte de coisas chatas não incluídas por questões de brevidade):
E, portanto, você tem um teste de unidade que chama o DAO e está usando os dados que foram configurados em um banco de dados dinâmico que existe durante a duração do teste. Você não precisa se preocupar com recursos externos ou com o estado do banco de dados antes da execução ou com a restauração para um estado conhecido (bem, o 'estado conhecido' é 'não existe', o que é trivial para reverter).
O DBUnit pode fazer muito do que descrevi em um processo mais simples na configuração do banco de dados, na criação de tabelas e no carregamento dos dados. Se você precisar usar o banco de dados real por algum motivo, essa é de longe a melhor ferramenta a ser usada.
O código acima é parte de um projeto que eu escrevi para a prova de conceito TestingWithHsqldb on github
fonte
sql.syntax_mys=true
que alteram a maneira como o hsqldb funciona: "Esta propriedade, quando definida como verdadeira, habilita o suporte aos tipos TEXT e AUTO_INCREMENT e também permite a compatibilidade com outros aspectos desse dialeto". whilesql.syntax_ora=true
"Esta propriedade, quando definida como verdadeira, habilita o suporte a tipos não-padrão. Também habilita as sintaxes DUAL, ROWNUM, NEXTVAL e CURRVAL e também permite a compatibilidade com alguns outros aspectos desse dialeto".Primeiro, você nunca deve fazer testes em um ambiente de produção. Você deve ter um ambiente de teste que espelhe seu ambiente de produção e faça testes de integração lá.
Se você fizer isso, poderá fazer várias coisas.
fonte
Em nosso projeto, cada desenvolvedor está executando um banco de dados vazio, sua estrutura é a mesma do banco de dados de produção.
Em cada teste de unidade TestInitialize, criamos uma conexão e transação com o banco de dados, além de alguns objetos padrão necessários para cada teste. E tudo é revertido após o final de cada método ou classe.
Dessa forma, é possível testar a camada sql. De fato, toda consulta ou chamada ao banco de dados deve ser testada dessa maneira.
A desvantagem é que é lento, então o colocamos em um projeto separado dos nossos testes de unidade regulares. É possível acelerar isso usando um banco de dados na memória, mas a idéia permanece a mesma.
fonte