JUnit - Testar método com retorno "void"

Bom dia Pessoal,

Lendo alguns posts aqui do fórum, eu percebi que deveria começar a me preocupar mais com Unit Testing.
Trabalho em uma empresa pequena, onde tem apenas 2 programadores Java e outros PHP / Webdesigner, etc. Assim fica fácil fazer mudanças sem burocracia.

Ontem, eu e meu parceiro começamos a fazer alguns testes com JUnit + Mock object e realmente funcionaram como esperado.

Porém olhando o nosso código atual, existem vários métodos sem retorno (void), e são métodos importantes. Por exemplo:

NotaFiscal nota = new NotaFiscal();
nota.setClientes(clientes);
nota.setProdutos(produtos);
nota.efetuarCalculos(); //aqui está o método que eu quero testar
nota.imprimirNota();

Como podem ver no exemplo acima, eu tenho um método importante (efetuarCalculos()) que não tem retorno, na verdade ele pega os dados já definidos dentro do objeto nota, faz os calculos e armazena os valores dentro de atributos, que serão utilizados depois no método imprimirNota.

No caso acima, eu gostaria de testar o método efetuarCalculos sem usar o imprimirNota, porque o imprimirNota de fato, irá mandar dados para a impressora.

Alguem poderia me ajudar com esse problema?

Obrigado desde já pessoal

Espero que ajude:

http://junit.sourceforge.net/doc/faq/faq.htm#tests_4
http://forum.java.sun.com/thread.jspa?threadID=662501&messageID=3884797

Fazendo seu efetuarCalculos() “throws CalculoException” pode ser uma alternativa.

:thumbup:

Verifique se após executar os métodos, os atributos modificados estão com os valores desejados.

A questão é que os atributos modificados são private e não pertencem a interface da classe, é utilizado apenas internamente.

crie um método público get que retorne a/as variáveis. Ou mesmo substitua o toString da classe com os métodos em um encadeamento que você possa recuperar e avaliar o output

A questão é que os atributos modificados são private e não pertencem a interface da classe, é utilizado apenas internamente.[/quote]

Você tem ao menos 2 opções:

  • Mudar atributos para protected e colocar a classe de teste no mesmo pacote da classe que está querendo testar
  • Usar métodos que retornem valores para estes atributos

Ambas as soluções podem deixar seu código “menos bonito” do ponto de vista de OO, mas serão testáveis mais facilmente.

Eu sou mais radical aqui.

A verdadeira beleza dos testes começa a aparecer quando você se obriga a testar o seu código. Percebeu que é difícil de testá-lo?

Isso indica um pequeno problema na sua classe. Perceba que quem usa a classe precisa se lembrar de chamar efetuaCalculo() antes de imprimirNota(). O que acontece se ele esquecer? Problema?

O teste te indicou um problema de design, justamente pq está difícil de testar. No seu lugar eu refatorava e juntava os dois métodos em um só.

Juntando os métodos eu não estaria acabando com a coesão do método?

[]s

De forma alguma, a responsabilidade pode continuar sendo dividida entre os dois. O ruim é obrigar quem usa a chamar métodos a mais só para “configurar” o seu objeto.

public void imprime() {
  efetuaCalculos();
  // ...
}

private void efetuaCalculos() {
  // ...
}

Concordo com o Fabio. Uma parte muito legal dos testes é que comecamos a perceber dependencias muito grandes, metodos com muita responsabilidade, classes estranhas, etc…

Se voce assumir uma postura de test driven desgin (nao precisa nem ser xiita de digitar o teste antes, mas SEMPRE ir fazendo os testes paralelamente), vai perceber que suas classes ja vao nascer mais desacopladas…

Deixa eu dar meu pitaco aqui.

Também concordo que no exemplo citado, o design da aplicação possa ser alterada para fazer mais sentido.

Porém, quebrando em vários métodos privates, como ficariam os testes? Um teste para o método “public” que internamente chama varios métodos privates, ou fazer um teste para cada método private? Se a segunda opçao for a correta, a melhor forma de testar um método private seria utilizando reflection entao?

Interpretei mal quando vc disse:

Depende de cada caso Jair. Do jeito que está agora eu só testaria o método público. Mas se você perceber que os métodos privados estão com responsabilidades importantes e que é importante testá-los, refatora denovo , extrai o comportamento pra uma classe separada e testa a nova classe.

Show de bola Fábio, muito obrigado pelas dicas, alias, estou aprendendo bastante com esse tópico sobre JUnit.

Com essas e outras, começamos a notar como refatoramente é importante e necessário sempre.

Agora a pergunta do Marcos, acho que agora ficou claro para ele, como ele deve proceder :wink: , e eu daqui para frente irei prestar mais atenção na minha modelagem/implementação