JUnit - Testar método com retorno "void"

13 respostas
M

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

13 Respostas

keller

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:

otaviofcs

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

M

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

otaviofcs

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

s4nchez

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

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.

Fabio_Kung

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ó.

brunohansen

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

[]s

Fabio_Kung

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() {
  // ...
}
Paulo_Silveira

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…

Jair_Rillo_Junior

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?

brunohansen

Interpretei mal quando vc disse:

Fabio_Kung

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.

Jair_Rillo_Junior

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

Criado 27 de junho de 2007
Ultima resposta 28 de jun. de 2007
Respostas 13
Participantes 8