Testes com DBUnit & HSQLDB

Olá Pessoal, 

Hoje veremos como deixar nossos testes com DBUnit usando o HSQLDB. O motivo que queremos rodar o banco em memoria, ou seja, evitarmos de termos que ter o banco rodando para executar os testes, o mesmo será iniciado somente quando os testes forem executado. Como você pode observar no último post, sempre temos que ter o MySql rodando para que as coisas funcionem e  ter essa dependência no dia-dia enquano estamos desenvolvendo é ruim, pois vamos exigir que cada desenvolvedor tenha que ter o MySql instalado na maquina etc. Não queremos isso. Queremos que ele faça o checkout do código e possa rodar. 

Lets go…

Starting…

Como já falado no post  anterior vimos como automatizar nossos testes usando DBUnit + Mysql, porém o que vimos de ruim é o fato de ter sempre o serviço do MySql rodando. E se quisermos rodar isso em memoria, como fazer? O HSQLDB nos dá uma mãozinha para rodar nossos testes com o HSQLDB, é muito simples, basta alterarmos o hibernate.cfg.xml e ter o .jar do HSQLDB adicionado ao projeto.

Vou considerar que você tem o projeto anterior, mas caso não tenha, siga os passos do primeiro post e mude apenas o arquivo do hibernate.cfg.xml.

1. O primeiro passo é criar o arquivo hibernate.cfg.xml com as configurações do banco onde os testes serão executados.

<hibernate-configuration>

<session-factory>

<property name=“hibernate.connection.driver_class”>org.hsqldb.jdbcDriver</property>

<property name=“hibernate.connection.url”>jdbc:hsqldb:mem:db</property>

<property name=“hibernate.connection.username”>sa</property>

<property name=“hibernate.dialect”>org.hibernate.dialect.HSQLDialect</property>

<property name=“hibernate.show_sql”>true</property>

</session-factory>

</hibernate-configuration>

Pronto, feito isso basta rodar os testes novamente e done. O resultado é Green .  Simples, não? Assim tiramos a dependência do MySql.

Vou ficando por aqui… Essa foi fácil.

Abraços, see ya!!

Automatizando seus testes com DBUnit + MySQL

olá Pessoal, 

No post de hoje vamos ver como rodar unit tests usando o DBUnit com MySql.  O DBUnit é uma API para fazermos testes unitários usando um banco de dados.

Starting…

Para rodar os testes automatizados é muito simples: precisamos apenas escolher o banco que vamos rodar e de um (ou mais) arquivos .xml que vai representar os dados a serem testados.

***Crie um projeto Java.

1. Primeiro passo é criar o arquivo hibernate.cfg.xml com as configurações do banco onde os testes serão executados.

<hibernate-configuration>

 <session-factory >

  <property name=“hibernate.connection.driver_class”>org.gjt.mm.mysql.Driver</property>

  <property name=“hibernate.connection.password”>camilo</property>

  <property name=“hibernate.connection.url”>jdbc:mysql://localhost/test</property>

  <property name=“hibernate.connection.username”>root</property>

  <property name=“hibernate.dialect”>org.hibernate.dialect.MySQL5InnoDBDialect</property>

  <property name=“hibernate.show_sql”>true</property>

 </session-factory>

</hibernate-configuration>

2. Criar uma classe que obtém a SessionFactory com  base nas informações do arquivo hibernate.cfg.xml

 

public class HibernateUtil {

       private static SessionFactory sessionFactory;

       public static SessionFactory getSessionFactory() {

             sessionFactorynew Configuration().configure().buildSessionFactory();

             return sessionFactory;

       }     

}

3. Criaremos um arquivo .xml (chame como quiser, chamarei de datalogin.xml. Ele deve tá no src do seu projeto)que representa a tabela do banco, conforme abaixo:

 

<?xml version=“1.0” encoding=“UTF-8”?>

<dataset>

<login id=“1” login=“camilo” senha=“124”/>

<login id=“2” login=“neto” senha=“234”/>

</dataset>

 

4. Agora vamos criar a nossa classe de Teste. Para questão apenas de explicação, subscrevi alguns métodos da classe do DBunit para explicar como as coisas funcionam, porém em outros é necessário implementarmos para que o DBunit saiba onde ele terá que conectar e pegar os dados:

public class DBunitTest extends DatabaseTestCase{

       private Session session;

       private IDatabaseConnection conn;

       private IDataSet dataSet;

       private FileInputStream loadFile;

       public DBunitTest() {

             try {

                    session = HibernateUtil.getSessionFactory().openSession();               

             } catch (Exception e) {

             e.getMessage();

             }

       }

       @Before

       public void setUp() throws Exception { 

//           a cada execução dos testes ele limpa e insere

             getSetUpOperation();      

       }

//     limpa tudo que tem nas tabelas e faz um insert

       @Override

       protected DatabaseOperation getSetUpOperation() throws Exception {

             return DatabaseOperation.CLEAN_INSERT;

       }

/* aqui que o pulo do gato

 * (non-Javadoc)

 * @see org.dbunit.DatabaseTestCase#getConnection()

 * fornecemos a forma de conexão ao banco, estou usando o Hibernate

 * não usar o método session.getConnection() ele está deprecated e vai sumir na versão 4.0

 */

       @Override

       protected IDatabaseConnection getConnection() throws Exception {

             conn = new DatabaseConnection(new Configuration().configure().buildSettings().getConnectionProvider().getConnection());

             return conn;

       }

/*

 * (non-Javadoc)

 * @see org.dbunit.DatabaseTestCase#getDataSet()

 *

 * fazer o load dos dados que serão testados

 */

       @Override

       protected IDataSet getDataSet() throws Exception {

             loadFile = new FileInputStream(“src/datalogin.xml”);

             dataSet =  new  FlatXmlDataSet(loadFile);

             return dataSet;

       }

}

Para facilitar o entendimento, a explicação está nos comentários in line, assim você lê, olha e aprende direto no código.

Testando

Agora vamos testar. Para isso, certifique-se que o MySql foi inicializado e adicione no final da classe DBunitTest o seguinte teste:

@Test

       public void testCheckLoginDataLoaded() throws Exception{

             assertNotNull(getDataSet());

             int rowCount = getDataSet().getTable(“login”).getRowCount();

             assertTrue(rowCount!=0);   }

 O teste é muito simples, apenas quero garantir que estamos conectados ao BD com os dados do dataset (observe que temos assert que verifica isso).  O resultado será:

Simples, não? Agora é apenas adicionar os cenários de testes no seu dataset, fazer as devidas implementações do DAO e chamar através dos seus testes.

Vou ficando por aqui.

See ya!! 

Criando GenericDAO e DAOFactory em poucos passos

Ola pessoal,

No post de hoje vamos ver como criar genericDAO e DAOFactory  em poucos passos. O objetivo maior aqui é colocar a mão na massa. Os conceitos DAO Design Pattern não serão abordados, pois o que não falta é explicação na internet sobre o assunto. Vou considerar que você sabe conceitualmente um DAO, mas que nunca implementou  de forma genérica.

Lets go…

 

Primeiro passo

Cria a interface GenericDAO :

public interface GenericDAO<T,Type extends Serializable> {

void beginTransaction();

void commitTransaction();

void save(T entity);

void delete (T entity);

List<T> listAll();

}

O código acima usa apenas o recurso de generics do Java 5, deixando a interface que extends dizer qual será o tipo para T e o para Type.

O que significa cada um?

Simples: o T será a classe, ou seja, a entidade. O Type representará o tipo que usaremos para o Id da entidade. Você pode estar se perguntando pq a letra T e a palavra type. Apenas segui uma convenção, mas poderia ser qualquer outra letra ou nome.

Agora precisamos criar a interface dos nossos DAO, que nesse caso teremos as seguintes interfaces: ClientDAO e AccountDAO.

public interface AccountDAO extends GenericDAO<Account, Long>{

}

public interface ClientDAO extends GenericDAO<Client, Long> {

}

Observe que nas nossas interfaces é que definimos para qual entidade ela está associada e qual será o tipo do nosso ID.

É nessa interface que colocamos os métodos específicos para o nosso DAO.

Abstract HibernateDAO

Criaremos uma classe abstract que vai implementar o métodos abstract da interface GenericDAO. E nossas classes concentras vão extends a HibernateDAO como veremos a seguir. Mas antes disso precisamos criar uma classe utilitária que chamei de HibernateUtil, que terá o método para obtermos a sessão, iniciar a transação, commit, etc.

public class HibernateUtil {

private static SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();

private static ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();

public static Session getSession() {

Session session = threadLocal.get();

if (session == null) {

session = sessionFactory.openSession();

threadLocal.set(session);

}

return session;

}

public static void beginTransaction() {

getSession().beginTransaction();

}

 public static void commitTransaction() {

getSession().getTransaction().commit();

public static void rollBackTransaction() {

getSession().getTransaction().rollback();

}

public static void closeSession() {

getSession().close();

}

}

E na classe HibernateDao temos o código a seguir:

public abstract class HibernateDAO<T, Type extends Serializable> implements GenericDAO<T, Type>{

private Class<T> persistentClass;

public HibernateDAO(Class persistentClass) {

super();

this.persistentClass = persistentClass;

}

@Override

public void beginTransaction() {

HibernateUtil.beginTransaction();

}

@Override

public void commitTransaction() {

HibernateUtil.commitTransaction();

}

@Override

public void save(T entity) {

HibernateUtil.getSession().saveOrUpdate(entity);

}

@Override

public void delete(T entity) {

HibernateUtil.getSession().delete(entity);

}

@Override

public List<T> listAll() {

HibernateUtil.beginTransaction();

Criteria criteria = HibernateUtil.getSession().createCriteria(persistentClass);

return criteria.list();

}

}

Observe que implementamos todos os métodos da GenericDAO, assim a classe que extends já tem a implementation done, ou seja, aquilo que é comum para qualquer  classe DAO já vai estar implementado e disponível na classe pai.

Concrete DAO

Agora vamos criar a classe concreta que terá a implementação específica para cada DAO.

class HibernateClientDAO extends HibernateDAO<Client, Long> implements  ClientDAO {

public HibernateClientDAO(){

//                           we passing the entity for super class

super(Client.class);

}

}

Como não temos nada de específico para implementar da interface ClientDAO deixaremos o código assim. Observe que no construtor passei qual será o tipo T, que nesse caso será a class do Client.

DAOFactory

Agora vamos criar um DAOFactory que será responsável por criar as instâncias das classes Hibernate. A classe DAOFactory será abstract e tendo apenas um método implementado que será o getFactory, o qual terá como objetivo simplesmente de retornar uma instância da classe.

public abstract class DAOFactory {

private static final Class FACTORY_CLASS = HibernateDAOFactory.class;

public static DAOFactory getFactory(){

try {

return (DAOFactory) FACTORY_CLASS.newInstance();

} catch (InstantiationException e) {

// TODO Auto-generated catch block

throw new RuntimeException();

} catch (IllegalAccessException e) {

// TODO Auto-generated catch block

throw new RuntimeException();

}

}

public abstract ClientDAO getClientDAO();

public abstract AccountDAO getAccountDAO();

}

Em seguida adicionamos os métodos que retornam a instância para as classes que implementam as interfaces ClientDAO e AccountDAO.

Agora teremos uma classe que implementa os métodos do DAOFactory, que será a classe HibernateDAOFactory.

public class HibernateDAOFactory  extends DAOFactory{

@Override

public ClientDAO getClientDAO() {

return new HibernateClientDAO();

}

@Override

public AccountDAO getAccountDAO() {

return new HibernateAccountDAO();

}

}

Observe que apenas instanciamos as classes para cada DAO. Agora vamos criar  HibernateAccountDAO

class HibernateAccountDAO extends HibernateDAO<Account, Long> implements AccountDAO {

public HibernateAccountDAO() {

super(Account.class);

}

}

E para testar, criaremos uma classe com o método main:

public class MainBank {

public static void main(String[] args) {

//                           getting instance of the factory

DAOFactory daoFactory = DAOFactory.getFactory();

//                           getting intance of clientDAO and starting transaction

daoFactory.getClientDAO().beginTransaction();

ClientDAO clientDAO = daoFactory.getClientDAO();

Client client = new Client();

client.setName(“Camilo Lopes”);

//                           creating object of the entity

Account checkigAccount = new Account();

checkigAccount.setAccountType(AccountType.CHECKING_ACCOUNT);

//                           associate acocunt with the client

checkigAccount.setClient(client);

//                           money available in account

checkigAccount.setBalance(BigDecimal.ONE);

client.getAccount().add(checkigAccount);

//                           saveing in hibernate session

clientDAO.save(client);

AccountDAO accountDAO = daoFactory.getAccountDAO();

accountDAO.save(checkigAccount);

//                           commit

clientDAO.commitTransaction();

}

}

Resultado

É isso ai pessoal, espero que tenham gostado. Vou ficando por aqui. 

See ya!!!

Pré-Lançamento: Livro TDD na Prática

Olá pessoal,

É com muita felicidade que escrevo este post. Realmente só quem é “pai” sabe o que eu estou sentido. Como vocês já podem imaginar está vindo ai mais um filho para se juntar aos seus irmãos “Guia do exame SCJP” e “Guia Prático JEE”. É ele o “TDD na Prática”. O livro está previsto para ser publicado até o final de junho/2012. Ainda não recebi a versão final do livro, mas assim que receber estarei disponibilizando alguns capítulos. A seguir faço uma pequena apresentação sobre o meu filhão.

lets go…

Sumario Tdd na Prática

Sobre o livro

O livro vem com um objetivo simples: “Descomplicar o que parece ser complicado”, em outras palavras O objetivo é ensinar como praticar TDD usando a linguagem de programação Java. Para muitos iniciantes em TDD, no primeiro momento parece que estamos fazendo tudo errado e que escrever os testes antes do código funcional não é nada legal. E que para superar os primeiros obstáculos, só o conhecimento técnico não é suficiente. Quando comecei com TDD passei por vários obstáculos e um deles foi encontrar livros práticos, ou seja, aqueles que eu pudesse colocar a mão na massa de verdade, ter problemas para resolver usando a técnica, etc. Os disponíveis eram bastante teórico, deixando a parte prática sobre minha responsabilidade que, como iniciante, era difícil saber por onde começar. Esses livros foram importantes para entendimento e formação da minha base teórica sobre o assunto, mas eu percebi que uma coisa era eu ter lido e outra era praticar e me ver com o Eclipse aberto e sem saber o que fazer de verdade, ou pior, me perguntar: ‘como resolver um problema usando TDD e não cair na tentação de escrever os testes por último?’. Quem não tem cão caça com gato. Tive que criar meu próprio caminho prático, onde comecei a desenvolver novas aplicações usando a técnica (venci pela persistência), em seguida surgiu  a oportunidade de ir para um projeto novo na empresa que trabalhava e lá tive o espaço para desenvolver usando TDD por quase 2 anos, e nesse meio surgiu a ideia desse livro: “por que não criar um livro prático sobre TDD com base na minha experiência?”. E foi assim que comecei a escrever o livro no final de 2010, tendo como referência o Kent Beck.  

O que você vai encontrar no livro:

  • Desenvolver aplicações Java usando a técnica de TDD;
  • Exercícios Práticos;
  • O uso de objetos mocks com Mockito;
  • Praticar algumas técnicas de Refactoring ;
  • Entender os valores do mundo Agile;
  • Por que TDD?
  • Junit;

E como sempre, dei preferência em usar uma linguagem informal e fazendo o uso bastante da primeira pessoa. O motivo é que durante seus estudos quero que tenha a sensação de estar batendo um papo comigo ao invés de estar lendo algo mais formal.

Meu desafio

Quando eu decidi escrever esse projeto foi porque me sentir desafiado (assim como os outros já publicados). É isso mesmo. Ao olhar o que tinha em mãos (anotações) mais a experiência e sofrimento com o “mundo TDD” e decepções que passei eu disse: “preciso escrever um livro sobre o assunto”. Daí reparei que escrever um livro com um assunto abstrato não seria uma tarefa fácil, uma vez que TDD, refactoring são técnicas que não se aplicam somente à linguagem Java. E daí eu comecei a entender melhor o livro do Kent Beck (TDD by example) e Martin Fowler (o de Refactoring) o quanto eles são “chatos” e sem sabor para quem é bem iniciante. E eu disse: “preciso fazer algo que empolgue o iniciante, ou seja, algo com sabor, mas que eu não venha perder o eixo principal da técnica”. E daí passei dias pensando, escrevendo, apagando, anotando, dormindo sem respostas e fui vendo como vencer esse desafio de ensinar TDD sem ferir os conceitos da técnica. Isso era o que me tirava o sossego todos os dias e não sei se consegui atingir. Acredito que sim, mas só terei a certeza quando você me escrever dizendo o que achou J. (aguardem até o lançamento…)

Quem pode ler?

O publico alvo são estudantes da tecnologia Java que querem aprender usar TDD desde o principio e tem simpatia com o mundo Agile.Se você ainda está dando os primeiros passos com Java e gosta de ser desafiado, este livro é para você. Indiretamente o livro acaba revisando alguns conceitos básicos do Java nada fora do normal, porém agora o desafio é você fazer as coisas mais simples escrevendo seu teste primeiro. Como eu já passei por isso, sei o quanto difícil é escrever os testes primeiro antes do código funcional e quando eu falo mais simples, não necessariamente é mais fácil.  Se você está bem no inicio do Java, ainda dando “Hello World”, eu diria que o livro não vai ajudar muito nos seus estudos com Java, talvez atrapalhe. A minha sugestão é: aprenda primeiro os fundamentos da linguagem e Orientação à Objetos e depois retorne à todo vapor para ler o livro. Enquanto isso coloque na prateleira e não compre o exemplar.

Pensei em escrever este livro quando, ao iniciar meus estudos com Java, não encontrei um material do qual pudesse desde “pequeno” ir sendo educado com boas práticas, e fui aprendendo no dia-dia, além dos sofrimentos que tive até adquirir uma nova cultura. Se você é aquele iniciante que está a fim de colocar em prática toda essência do Java e ao mesmo tempo ir entendendo o que só ouve falar de TDD, Refactoring, JUnit, este livro é para você.

Eu particularmente diria que este é um tipo de livro que gostaria de ler depois de ter lido Head First Java da Kathy Sierra.

Agradecimentos

Fazer essa parte aqui nunca é fácil, pois são várias pessoas que contribuem para uma obra como essa: amigos, colegas de trabalho, familiares, “amigo virtual” etc. E lembrar todos não é uma tarefa fácil. Sendo assim, estarei destacando aqueles que vieram em memória no momento que escrevo este trecho. Aqueles que contribuíram e acabei esquecendo, peço que perdoem.

Não poderia esquecer o meu colega de trabalho Gustavo Knuppe, apesar dele não saber que estava escrevendo este livro, foi responsável em muitas mudanças que fiz na forma de abordar o assunto de TDD.Principalmente em um artigo sobre TDD, o qual Knuppe foi o revisor, e nesse processo, sugiram várias e boas sugestões no artigo produzido e aproveitei para utilizar neste projeto. Um amigo que não poderia deixar de fora é o Alberto Leal. Eu diria que meu contato com mundo Agile começou devido a uma apresentação sobre refactoring que o Leal fez em alguns minutos via MSN e depois desse dia fui me envolvendo mais e mais com a técnica e quando conheci TDD e liguei o passado com o presente vi que ter conhecido refactoring com o Alberto fez uma diferença e grande. Obrigado meu amigo!

Outra pessoa é meu amigo Edson Gonçalves, sempre digo que se me tornei um escritor é porque fui “batizado” por esse grande escritor e amigo, o qual já temos um laço de amizade verdadeira por mais de quatro anos. Dedicar este livro para um grande amigo como você é o mínimo que posso fazer. Nos momentos mais difíceis você sempre estava ali comigo me dando força. Abraços e tudo de bom para você meu grande amigo.

Formatos

  • Será vendido no formato impresso e e-book.

Enfim, pessoal essa foi a pequena apresentação do meu próximo livro. Espero que vocês gostem e curtam. Quem quiser divulgar nas comunidades eu não me importo 🙂

Abraços, qualquer dúvida só mandar.

See ya!!!

Criando Mocks com Mockito

olá Pessoal,

No post de hoje vamos ver como usar o API Mockito para criação de objetos mocks. No ultimo post vimos o que são mocks, mas eu já tinha falado rapidamente do Mockito. Usarei o mesmo exemplo visto no post passado, porém agora teremos mocks in action.

Lets go…

Usando JUnit com o Mockito

Para não ter que repetir o código anterior, neste post adicionei apenas a classe que tem o unit test. Então, vou considerar que você viu o nosso post sobre Mocks.

Agora precisamos testar a classe AlugaCarro e ver se de fato ela está retornando um objeto que possui as informações que esperamos que tenha.

Classe de teste

publicclass CarroAlugadoTest {

@Mock

private AlugaCarro alugaCarro;//my interface

public CarroAlugadoTest() {

alugaCarro = Mockito.mock(Cliente.class);

}

@Test

publicvoid alugaCarroParaCliente(){

//o caraquerecebeoscarrosalugados

CarroAlugado car = new CarroAlugado(alugaCarro);

String resultadoEsperado = “Camilo Golf”;

/*

* aqui o clientecamiloestáreservando o carro golf

*/

Mockito.when(alugaCarro.getNomeCliente()).thenReturn(“Camilo “);

Mockito.when(alugaCarro.getModeloCarro()).thenReturn(“Golf”);

String verdadeiroResultado = car.getAlugaCarro().getNomeCliente() + car.getAlugaCarro().getModeloCarro();

Mockito.verify(alugaCarro).getNomeCliente();

assertEquals(resultadoEsperado,verdadeiroResultado);

}

Explicado partes importantes do código

Passo 1

Precisamos fazer a mock,ou seja, “mockar” uma classe/interface, há várias formas de fazer isso, usaremos o modo mais simples, que é usar annotations @Mock na variável que vai ser o objeto e “instanciar” ela no construtor, pois quando a classe for carregada a variável será “mockada”.

@Mock

private AlugaCarro alugaCarro;

public CarroAlugadoTest() {

alugaCarro = Mockito.mock(Cliente.class);

}

Passo 2

Criamos um teste onde vamos verificar se um carro foi alugado para o cliente.

Primeiro passo foi passar o objeto “mockado” que representa “o cliente” para a classe CarroAlugado, pois é isso que ela espera receber, um objeto que alugou um carro.

  1. CarroAlugado car = new CarroAlugado(alugaCarro);

Em seguida vamos configurar os valores para o método que recebe o nome do cliente e o que recebe o nome do carro alugado. Porém, aqui usaremos API Mockito. Essa linha de código será executada quando o método for invocado.

  1. Mockito.when(alugaCarro.getNomeCliente()).thenReturn(“Camilo “);
  2. Mockito.when(alugaCarro.getModeloCarro()).thenReturn(“Golf”);

A leitura poderia ser algo do tipo: “quando o metodo getNomeCliente() for chamado, então configure o valor dele para “camilo”.

Na linha seguinte, observe que chamamos os métodos, que acreditamos estarem com um valor. E ai o mockito entra in action, quando um objeto, chama um daqueles métodos, ele configura os valores que estão no thenReturn().

  1. String verdadeiroResultado = car.getAlugaCarro().getNomeCliente() + car.getAlugaCarro().getModeloCarro();
  2. Mockito.verify(alugaCarro).getNomeCliente();

O método verify() apenas verifica se o método foi chamado, no API Docs do Mockito, há outras pessoas de verificação, como por exemplo:

  • verificar se o metodo getNomeCliente() foi chamado pelo menos 1 vez, ou mais vezes;
  • verificar se nunca foi chamado.

O assertEquals é somente para verificar se estamos recebendo o valor esperado.

Outro teste que foi implementado:

@Test

publicvoid verificaSeUmMetodoNuncaFoiExecutado(){

CarroAlugado carroAlugado = new CarroAlugado(alugaCarro);

Mockito.when(alugaCarro.getModeloCarro()).thenReturn(“Civic”);

//verificase o metodo getNomeCliente() nuncafoiexecutado

String modeloCarro = carroAlugado.getAlugaCarro().getModeloCarro();

Mockito.verify(alugaCarro, Mockito.never()).getNomeCliente();

}

Um video

Um video do Vinicius mostra a diferença entre mock & Stubs que achei muito bom.

http://viniciusquaiato.com/blog/diferenca-entre-mocks-e-stubs/

Conclusão

Uma outra dica é você gastar um bom tempo ali na documentação do Mockito, ela é bastante rica e de fácil leitura. A API não é tão grande e muito menos complexa, basta um pouco de pratica e sabendo como usar cada recurso, tá feito.

Vou ficando por aqui e espero que tenham gostado do post.

Abracos, see ya!