Com VRaptor e Mockito é muito mais fácil testar!

E ai negada, depois de um tempão sem postar nada(Faculdade e o novo estágio agradecem), estou de volta para falar um pouco sobre um assunto que tenho dando bastante  ênfase que são os testes. Pretendo escrever dois artigos falando sobre tal. O primeiro a seguir abordando os testes de unidade e o próximo a respeito dos testes de integração. Então vamos lá.

           “Usando TDD, quando acabamos, realmente acabamos. Ou seja, dificilmente temos que retornar ao código futuramente para corrigir falhas, pois possíveis falhas já foram detectadas e corrigidas durante a confecção dos testes.”
Com essa citação que pode ser encontrada no site da ImproveIt, damos início a um dos temas “quentes” do momento que são os testes. Mas o que é esse TDD?Bem, TDD (Test Driven Development) é uma das práticas abordadas na metodologia XP, que se baseia em escrever os testes antes de programarmos o código-fonte. Legal essa idéia do TDD, mas o post irá focar nos testes, especificamente nos testes de unidade ou testes unitários. Então XP fica para a próxima.
O teste unitário ou de unidade é uma modalidade de testes que se concentra na verificação da menor unidade de código funcional do projeto de software. Como estamos no mundo OO, essa menor unidade pode ser entendida a um objeto ou mesmo a um comportamento do mesmo, reagindo a um estimulo (métodos da classe). Com entradas que são parâmetros e as saídas são o valores de retorno, exceções ou o estado do objeto.
O que será demonstrado nesse post, será desde uma explicação de testes, com exemplos simples sobre testes unitários. Até aprofundarmos mais, mostrando testes em uma classe de controle do VRaptor, passando pelo conceito de Mock Object, abordando as facilidades que  VRaptor traz, afim de “Mockar” os objetos do framework.
Para implementar os testes usaremos o bastante conhecido JUnit, ele escreve testes em Java e se integra facilmente com qualquer IDE (Eclipse, NetBeans, whatever).
              Vamos a uma classe simples de teste do JUnit:
public class MathTeste {

@Test

public void somaTeste(){

        Assert.assertEquals(9, 5+4);

}

}

A primeira vista:
1. Nós dizemos ao Junit que aquele método é um teste pela annotation @Test.
2. Eu quero saber se o resultado 5+4 é IGUAL a 9(dã!!), daí o assertEquals. Não para por ai, a <a href=”http://junit.sourceforge.net/javadoc/org/junit/Assert.html”>classe Assert</a> possui inúmeros métodos de verificação.

E ao rodar o teste, o plugin do Junit na IDE(Eclipse no caso), “cospe” o resultado. Trata de um sinal verde, se seu teste passou. Vermelho se não passou (legal né?).

Ok. Passando a parte introdutória, vamos ao VRaptor. O VRaptor é um framework MVC em Java focado no desenvolvimento rápido e simples, e na fácil manutenção do código. Mais uma definição wiki.</div>
Beleza, mas nosso foco ainda não é entrar em detalhes sobre o VRaptor e como ele trabalha, mas sim TESTES. Assim vou mostrar a nossa classe de controller a ser testada(Limitaremos somente a funcionalidade de pesquisa).</div>

@Resource
public class FilmeController {

      private final Result result;
      private FilmeService filmeService;
      private Validator validator;

      public FilmeController(Result result, FilmeService filmeService, Validator validator) {
              this.result = result;
              this.filmeService = filmeService;
              this.validator = validator;
      }

      @Path("/filme")
      public void index(){
      }

      @Get
      @Path("/filme/pesquisa")
      public void pesquisa(Filme filme){
           List loadFilme = null;
           try{
                loadFilme = filmeService.pesquisar(filme);
                if(loadFilme.isEmpty()){
                      result.include("notice", "Nenhum produto encontrado!!");
                }
                result.include("filmes", loadFilme);
                result.forwardTo(this).index();
          }catch(Exception e){
                result.include("erros", e.getMessage());
          }
      }
            Show galera. Classe controller mostrada, agora vamos ao FilmeControllerTeste.java, nossa classe que realizará o teste unitário do FilmeController.java.
private Result result;
private Validator validator;
private FilmeController filmeController;

@Mock private FilmeService filmeService;
            Criamos esses objetos para simular o comportamento da classe a ser testada. Uma breve explicação.  Result, que é um componente do VRaptor que consegue mudar o resultado do seu método. Similar a classe HttpRequest da Api Servlet. A Interface Validator, que é passada como parâmetro no construtor da classe, oferece meios para realizar validações no seu controller.
             E esse Mock. “WTF” Mock?
Mock objects são objetos que simulam o comportamento de objetos reais. Mas pra que isso? Serve para prender o escopo dos seus testes. Por exemplo, se você esta fazendo um teste em uma classe de controle e o método desta classe invoca um método de uma classe de serviço que faz uma consulta no banco, você deve usar um Mock para simular o objeto desta outra classe, simulando assim esta consulta, pois a consulta será testada no momento em que o teste para o seu método for criado.

             Antes de implementar o primeiro teste, vamos inicializar.. é.. o que precisamos pra começar os testes(A annotation @Before  do JUnit é utilizada justamente para isso).

  • Todos os Mocks (utilizando o Mockito API, para trabalhar com os mocks).
  • Result e Validator(Vraptor já disponibiliza os mocks para esses objetos).
</pre>
@Before
public void setUp(){
      MockitoAnnotations.initMocks(this);
      result = new MockResult();
      validator = new MockValidator();
      filmeController = new FilmeController(result, filmeService, validator);
}

               E finalmente vamos começar a brincadeira. Primeiro vamos ao “happy day”, o que deve acontecer se a pesquisa for bem sucedida.

//obs: Fazemos os imports estásticos afim de melhorar a leitura do código:
// import static org.junit.Assert.*;
// import static org.mockito.Mockito.*;
// import static org.mockito.Matchers.any;

@Test
public void deveriaPesquisarFilmes(){
        when(filmeService.pesquisar(any(Filme.class))).thenReturn(new ArrayList());
        filmeController.pesquisa(any(Filme.class));

        assertTrue("deve haver uma lista de Filmes", result.included().containsKey("filmes"));
        assertFalse("n‹o deve exibir nenhuma msg de erro)", result.included().containsKey("erros"));
}
              Teste passando, vamos aos porquês. A Api Mockito eh bem intuitiva, ela possui  métodos estáticos de fácil entendimento, senão vejamos.  “Quando(when) um filmeService pesquisar (filmeService.pesquisar(…)) qualquer filme (any(Filme.class)), então me retorne uma lista de filmes (thenReturn(new ArrayList<Filme>());). Mais intuitivo que isso impossível. Importante é você entender a semântica(feeling) da coisa e saber(no sangue) o comportamento da sua classe. O resto é detalhe de sintaxe.”
Vamos ao revés.
</pre>
@Test
public void deveriaTratarORetornoDeUmaListaNull(){
      when(filmeService.pesquisar(any(Filme.class))).thenReturn(null);
      filmeController.pesquisa(any(Filme.class));

      assertTrue("deve exibir uma mensagem de erro", result.included().containsKey("erros"));
      assertFalse("n‹o deve exibir nenhuma msg de aviso)", result.included().containsKey("notice"));
      assertFalse("nao deve haver uma lista de Filmes", result.included().containsKey("Filmes"));
}
             Testando o que pode acontecer se o método não for bem sucedido, alguma exceção lançada, ou seja algo dando errado, é o ponto chave dos testes. Você prever o que pode dar errado no seu código(aqui estou verificando um único problema que possa ocorrer, por questão de não me estender ainda mais) e na mesma hora tratar e corrigir esse erros, vão lhe poupar tempo depois que seu sistema estiver em produção. Afinal, time is money. Não estou afirmando que com os testes, você estará segurado 100% de erros, mas certamente eles demorarão mais a ocorrer e a manutenção se tornará menos dolorosa. Sem falar na melhoria do design do seu código com o uso de testes(principalmente se você estiver usando TDD – Leia Clean Code!).
REFERÊNCIAS:
O código completo pode ser baixado no meu github: http://www.github.com/yuriadams.

2 Responses to Com VRaptor e Mockito é muito mais fácil testar!

  1. atos disse:

    E onde está o mockito do titulo do post????

    • Yuri Adams disse:

      1)@Mock private FilmeService filmeService;

      A annotation do mockitoque diz que esse FilmeService é um Mock.

      2) when(filmeService.pesquisar(any(Filme.class))).thenReturn(new ArrayList());

      Aqui os métodos when, any e thenReturn são da api do Mockito. Eles são bem legíveis. Aqui você deixa explícito o comportamento do seu mock.

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: