quarta-feira, 8 de fevereiro de 2012

Refatorando o método utilitário

Saudações…

Continuando o desenvolvimento do utilitário do post anterior (link). Vamos refatorar a funcionalidade para que atenda:
- String (java.lang.String)
- Collection (java.util.Collection)
- Map (java.util.Map)

Começaremos replicando as classes Util e UtilTest para o novo pacote (br.com.joelamalio.utilitario.terceiropost). Em seguida modificaremos o parâmetro do método isNullOrEmpty() de String para Object (java.lang.Object) e depois mudaremos:

//DE
} else if (valor.isEmpty()) {
    return true;
}
//PARA
} else if (valor instanceof String) {
    String string = (String) valor;
    return string.isEmpty();
}

Após o término da primeira etapa os testes continuarão a passar e as nossas classes ficarão assim:

package br.com.joelamalio.blogutilitario.terceiropost;

/**
*
* @author joelamalio
*/
public class Util {

    public static boolean isNullOrEmpty(Object object) {
        if (object == null) {
            return true;
        } else if (object instanceof String) {
            String string = (String) object;
            return string.isEmpty();
        }
        return false;
    }

}

package br.com.joelamalio.blogutilitario.terceiropost;

import org.junit.Assert;
import org.junit.Test;

/**
*
* @author joelamalio
*/
public class UtilTest {

    @Test
    public void testarSeAStringValorEhNulaEORetornoEhTrue() {
        String valor = null;
        boolean retorno = Util.isNullOrEmpty(valor);
        Assert.assertTrue(retorno);
    }

    @Test
    public void testarSeAStringValorEhVaziaEORetornoEhTrue() {
        String valor = "";
        boolean retorno = Util.isNullOrEmpty(valor);
        Assert.assertTrue(retorno);
    }

    @Test
    public void testarSeAStringValorNaoEhVaziaEORetornoEhFalse() {
        String valor = "@joelamalio";
        boolean retorno = Util.isNullOrEmpty(valor);
        Assert.assertFalse(retorno);
    }

}

Agora vamos modificar a implementação e criar os novos testes.

O segundo passo é criar um novo teste e validar se uma Collection está nula.

@Test
public void testarSeUmaCollectionEhNulaEORetornoEhTrue() {
    Collection collection = null;
    boolean retorno = Util.isNullOrEmpty(collection);
    Assert.assertTrue(retorno);
}

Como o valor do objeto (collection) é null e a primeira validação é da nulidade do objeto, o teste passará, pois o retorno do método é true. Devido a modificação do parâmetro para Object, o mesmo aceitará qualquer objeto. Sendo assim poderemos passar um Map, um Array (Object[]) ou qualquer outro objeto e o teste continuará a passar, ou seja, o método atenderá a qualquer objeto. Pois no final das contas todos são herdeiros de Object.

@Test
public void testarSeUmMapEhNuloEORetornoEhTrue() {
    Map map = null;
    boolean retorno = Util.isNullOrEmpty(map);
    Assert.assertTrue(retorno);
}

@Test
public void testarSeUmArrayDeObjectEhNuloEORetornoEhTrue() {
    Object[] array = null;
    boolean retorno = Util.isNullOrEmpty(array);
    Assert.assertTrue(retorno);
}

O terceiro passo é criar mais um teste e verificar se uma coleção instanciada está vazia ou não.

@Test
public void testarSeUmaCollectionInstanciadaEstaVaziaEORetornoEhTrue() {
    Collection collection = new ArrayList();
    boolean retorno = Util.isNullOrEmpty(collection);
    Assert.assertTrue(retorno);
}

O teste falhará, pois a variável retorno é false e o valor esperado foi true. Mas por qual motivo falhou? A resposta é simples. A falha aconteceu porque um objeto recém instanciado da classe ArrayList (java.util.ArrayList) é vazio por padrão. E o que faremos para atender a nova necessidade? Devemos alterar o nosso método para:

public static boolean isNullOrEmpty(Object valor) {
    if (valor == null) {
        return true;
    } else if (valor instanceof String) {
        String string = (String) valor;
        return string.isEmpty();
    } else if (valor instanceof Collection) {
        Collection collection = (Collection) valor;
        return collection.isEmpty();
    }
    return false;
}

Para validar a nova implementação devemos criar um novo teste com uma coleção com um ou mais objetos, e o teste passará.

@Test
public void testarSeUmaCollectionCom2ObjetosEstaVaziaEORetornoEhFalse() {
    Collection collection = new ArrayList();
    collection.add("Objeto 1");
    collection.add("Objeto 2");
    boolean retorno = Util.isNullOrEmpty(collection);
    Assert.assertFalse(retorno);
}

Podemos e vamos usar a mesma ideia com o Map. Criaremos um teste para validar se um Map instanciado está vazio.

@Test
public void testarSeUmMapInstanciadoEstaVazioEORetornoEhTrue() {
    Map map = new HashMap();
    boolean retorno = Util.isNullOrEmpty(map);
    Assert.assertTrue(retorno);
}

O método acima falhará. E em seguida vamos alterar a implementação do método isNullOrEmpty().

public static boolean isNullOrEmpty(Object valor) {
    if (valor == null) {
        return true;
    } else if (valor instanceof String) {
        String string = (String) valor;
        return string.isEmpty();
    } else if (valor instanceof Collection) {
        Collection collection = (Collection) valor;
        return collection.isEmpty();
    } else if (valor instanceof Map) {
        Map map = (Map) valor;
        return map.isEmpty();
    } 
    return false;
}

Para validar a nova implementação adicionaremos o teste abaixo.

@Test
public void testarSeUmMapCom2ObjetosEstaVazioEORetornoEhFalse() {
    Map map = new HashMap();
    String objeto1 = "Objeto 1";
    String objeto2 = "Objeto 2";
    map.put(objeto1.hashCode(), objeto1);
    map.put(objeto2.hashCode(), objeto2);
    boolean retorno = Util.isNullOrEmpty(map);
    Assert.assertFalse(retorno);
}

Código-fonte disponível em github.

Assim, termina o nosso terceiro post.

Até breve.

segunda-feira, 30 de janeiro de 2012

Começando com o JUnit

Hoje reservei um tempo para escrever o meu segundo post. Há alguns meses criei o blog e não tive mais tempo para atualiza-lo. Mas vamos que vamos…

A ideia é desenvolver um método utilitário. Seguindo as boas práticas e usando TDD.

As Ferramentas necessárias para o nosso trabalho:
- Java 1.6.0_29 (download);
- Netbeans 7.1 (download);
- JUnit 4.8.2 (download).

Vamos começar com uma ideia simples e desenvolver um método que tem como objetivo avaliar se uma String (java.lang.String) é nula (null) ou vazia (isEmpty()*) e aplicar os testes unitários necessários.

O primeiro passo é criar a classe Util (br.com.joelamalio.utilitario.segundopost.Util) no pacote código-fonte. Em seguida, devemos escrever apenas o código necessário para compilar o projeto.

package br.com.joelamalio.blogutilitario.segundopost;

/**
*
* @author joelamalio
*/
public class Util {

    public static boolean isNullOrEmpty(String valor) {
        //TODO implementar o método.
        return false;
    }

}

Depois criaremos a classe UtilTest (br.com.joelamalio.utilitario.segundopost.UtilTest) no pacote de testes e o nosso primeiro teste de unidade.

package br.com.joelamalio.blogutilitario.segundopost;

import org.junit.Assert;
import org.junit.Test;

/**
*
* @author joelamalio
*/
public class UtilTest {

    @Test
    public void testarSeAStringValorEhNulaEORetornoEhTrue() {
        String valor = null;
        boolean retorno = Util.isNullOrEmpty(valor);
        Assert.assertTrue(retorno);
    }

}

Quando executarmos o build do projeto, o Netbeans alertará um erro, informando que o valor da variável retorno é false e o mesmo deveria ser true, ou seja, o teste FALHOU.
Devemos refatorar o método testado para que ele PASSE. Após a primeira refatoração teremos:

public static boolean isNullOrEmpty(String valor) {
    if (valor == null) {
        return true;
    }
    return false;
}

Após um novo build o teste passará!

Agora já temos um método que valida se a nossa String é nula ou não. O próximo passo é verificar se a String está vazia. Vamos criar mais um teste.

@Test
public void testarSeAStringValorEhVaziaEORetornoEhTrue() {
    String valor = "";
    boolean retorno = Util.isNullOrEmpty(valor);
    Assert.assertTrue(retorno);
}

Novamente o teste falhará e deveremos refatorar o método testado.

public static boolean isNullOrEmpty(String valor) {
    if (valor == null) {
        return true;
    } else if (valor.isEmpty()) {
        return true;
    }
    return false;
}

Ao efetuarmos as mudanças no código o teste passará!
E por último devemos testar se a String não está vazia.

@Test
public void testarSeAStringValorNaoEhVaziaEORetornoEhFalse() {
    String valor = "@joelamalio";
    boolean retorno = Util.isNullOrEmpty(valor);
    Assert.assertFalse(retorno);
}

Código-fonte disponível no github
Assim termina o nosso segundo post.

Até breve.

_____
* Disponível desde o java 1.6.