Como testar um método void com JUnit?

12 respostas Resolvido
java
ClarissaAndrade

Olá,

Eu preciso testar um método, mas ele tem retorno void, como faço isso? Tentei dividir ele em dois métodos, um com algum retorno, e outro que imprimisse mas não consegui.

É uma classe Pizza, que adiciona os ingredientes em uma lista, e esse método contabiliza e imprime todos os ingredientes.

public void contaIngredientes() {
	for (String ingrediente : listaIngredientes) {
		int frequency = Collections.frequency(listaIngredientes, ingrediente);
		System.out.println(ingrediente + ": " + frequency);
	}
}

Quando existe mais de um ingrediente, o método contabiliza ele corretamente, mas imprime duas vezes o nome do ingrediente conforme a ordem que eles aparecem na lista. Vocês poderiam me ajudar a consertar isso também?

12 Respostas

Lucas_Camara

Como você está tentando testar esse método? Já tem algo escrito?

Testar métodos void é realmente algo mais complicado, pois depende do que o método tem que fazer. Nesse seu caso, ele vai contar os ingredientes. O bom é que o teste vai ajudar a identificar possíveis falhas no código escrito.

Nesse seu caso, seria mais fácil testar esse método se ele retornasse o total de ingredientes, isso iria fazer com que esse método fizesse mais sentido do que apenas imprimir algum valor no console com System.out.println.

Vc pode postar a classe completa para podermos entender melhor o objetivo dela? Vendo só esse método, a recomendação que faço é fazer com que ele retorne o total mesmo.

ClarissaAndrade

A classe completa é essa:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Pizza {

	static List<String> listaIngredientes = new ArrayList<>();
	double valorPizza = 0;
	static int quantidadeEstatica = 0;
	int quantidade = 0;
	
	public void adicionaIngrediente(String ingrediente) {
		listaIngredientes.add(ingrediente);
		quantidade++;
		contabilizaIngredientes();
	}

	public double getPreco() {
		if (quantidade <= 2) {
			valorPizza = 15;
			return valorPizza;
		}
		if(quantidade>=3 && quantidade<=5) {
			valorPizza = 20;
			return valorPizza;
		}
		else {
			valorPizza = 23;
			return valorPizza;
		}
	}
		
	public static void contabilizaIngredientes () {
		quantidadeEstatica++;	
	}	
	
	public void contaIngredientes () {
		
		for (String ingrediente : listaIngredientes) {
		int frequency = Collections.frequency(listaIngredientes, ingrediente);
		System.out.println(ingrediente + ": " + frequency);
		}
	}
		
	
	public static void zeraIngredientes() {
		quantidadeEstatica = 0;
		
	}

Eu tentei fazer o método retornar o frequency, em vez de imprimir ele na tela, só que daí ele só retorna o valor do primeiro item da lista. Aí eu tentei fazer ele retornar o frequency como uma lista, mas não consegui fazer isso, o código só dava erro. :frowning:

Lucas_Camara

Pelo que estou entendendo, o método contaIngredientes deve contar o total por tipo de ingrediente dentro da lista de ingredientes. Se for isso mesmo, o retorno desse método seja um Map, pois vc terá um total para cada ingrediente que é usado na lista de ingredientes. Ex.:

List<String> ingredientes = new ArrayList<>();
ingredientes.add("ingredienteA");
ingredientes.add("ingredienteA");
ingredientes.add("ingredienteB");
ingredientes.add("ingredienteB");
ingredientes.add("ingredienteB");
ingredientes.add("ingredienteC");

System.out.println(Collections.frequency(ingredientes, "ingredienteA")); // 2
System.out.println(Collections.frequency(ingredientes, "ingredienteB")); // 3
System.out.println(Collections.frequency(ingredientes, "ingredienteC")); // 1

É isso mesmo que esse método contaIngredientes tem que fazer?

ClarissaAndrade

É isso mesmo que o método tem que fazer.
A sua sugestão é que ele retorne um Map? Daí esse Map daria para testar?
Você pode me mostrar como eu faço isso, por favor?

Lucas_Camara
Solucao aceita

Classe Pizza com algumas modificações:

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Pizza {
    private static final List<String> ingredientes = new ArrayList<>();
    private double valorPizza = 0;

    public void adicionaIngrediente(String ingrediente) {
        ingredientes.add(ingrediente);
    }

    public double getPreco() {
        if (getTotalIngredientes() <= 2) {
            valorPizza = 15;
            return valorPizza;
        }
        
        if (getTotalIngredientes() >= 3 && getTotalIngredientes() <= 5) {
            valorPizza = 20;
            return valorPizza;
        } else {
            valorPizza = 23;
            return valorPizza;
        }
    }

    public Map<String, Integer> contarIngredientes() {
        Map<String, Integer> totalPorIngredientes = new HashMap<String, Integer>();
        
        for (String ingrediente : ingredientes) {
            int frequency = Collections.frequency(ingredientes, ingrediente);
            totalPorIngredientes.put(ingrediente, frequency);
        }
        
        return totalPorIngredientes;
    }
    
    public Integer getTotalIngredientes() {
        return ingredientes.size();
    }

    public void zerarIngredientes() {
        ingredientes.clear();
    }
}

Classe de Teste

import java.util.Map;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class PizzaTest {
    
    private Pizza fixture;
    
    @BeforeEach
    void setup() {
        fixture = new Pizza();
    }

    @Test
    public void devePossuirAQuantidadeCorretaDeIngredientes() {
        // Arrange
        fixture.adicionaIngrediente("ingredienteA");
        fixture.adicionaIngrediente("ingredienteA");
        fixture.adicionaIngrediente("ingredienteB");
        fixture.adicionaIngrediente("ingredienteB");
        fixture.adicionaIngrediente("ingredienteB");
        fixture.adicionaIngrediente("ingredienteC");
        
        // Act
        Map<String, Integer> actual = fixture.contarIngredientes();
        
        // Assert
        Assertions.assertEquals(2, actual.get("ingredienteA"));
        Assertions.assertEquals(3, actual.get("ingredienteB"));
        Assertions.assertEquals(1, actual.get("ingredienteC"));
    }

}
ClarissaAndrade

Caraca, Lucas! Valeu mesmo!
Estou fazendo um curso de Java, mas o curso é muito ruim, didática péssima, não ensina nada você a fazer as coisas e já pede pra entregar o exercício, aí estou perdidona. Mas, brigadão.

Lucas_Camara

Aqui no GUJ tem muita gente que entende bastante de testes, sem falar que teste é algo fundamental para um bom desenvolvimento e, em muitas vezes, deixado de lado. Aqui no meu trabalho a galera força muito a questão de testes (seja unitário, integração ou até mesmo funcional, dependendo do caso). Mas teste unitário sempre é bom fazer.

Esse seu exemplo é muito para fazer uns testes bacanas. Qualquer dúvida, soh falar.

Qual curso vc está fazendo?

obs.: Nessa classe de teste, usei o JUnit na versão 5 ok. Se vc rodar ele com a versão 4 do JUnit, não vai funcionar.

ClarissaAndrade

Eu estou fazendo um que é o primeiro módulo de uma especialização do ITA, chama Orientação a Objetos com Java, fica na plataforma Coursera. Mas não gostei.
Você conhece algum curso bom?
Eu trabalho com suporte hoje, mas em fevereiro vou começar a trabalhar com desenvolvimento, aí tava querendo ir praticando bastante antes de entrar.

Lucas_Camara

Uns cursos bem avaliados que vejo muito a galera comentar são esses:

Bacana, também comecei como suporte antes de ir para área de desenvolvimento.

Lucas_Camara

Se vc for trabalhar com java, recomendo que dê uma olhada em Spring, que é amplamente utilizado hoje em dia).

ClarissaAndrade

Valeu pelas dicas, Lucas!

Lucas_Camara

Marque depois a resposta que te ajudou como solução. Vlw!

Criado 11 de novembro de 2019
Ultima resposta 12 de nov. de 2019
Respostas 12
Participantes 2