JUnit Teste parametrizado com exemplo usando @Parameters
⚡ Resumo Inteligente
Testes parametrizados em JUnit Execute o mesmo método de teste repetidamente com diferentes valores de entrada, de forma que um único método cubra vários cenários. As anotações `@RunWith` e `@Parameters` fornecem o conjunto de dados para cada iteração.

O que é um teste parametrizado em JUnit?
A teste parametrizado É um teste que executa o mesmo método de teste repetidamente, usando valores diferentes. Ele ajuda os desenvolvedores a economizar tempo ao escrever testes que diferem apenas em suas entradas e resultados esperados.
Usando um teste parametrizado, é possível configurar um método de teste que recupera dados de alguma fonte de dados. Isso o torna a forma mais simples de... teste baseado em dados disponível dentro JUnit por si só, sem necessidade de biblioteca externa.
Considere um teste simples que soma números diferentes. O código pode ser semelhante a este:
A abordagem acima leva a muita redundância. Cada novo par de números precisa de uma nova instrução assert dentro do mesmo método, e uma falha na primeira asserção oculta todas as asserções subsequentes.
É necessária uma abordagem mais simples. Usando um teste parametrizado, você pode adicionar um único método que fornece dez entradas de dados, e seu teste será executado dez vezes automaticamente.
Etapas para criar um parametrizado JUnit Testar
O código a seguir mostra um exemplo de um teste parametrizado. Ele testa o método sum() da classe Airthematic, que é a grafia usada em todo o projeto de exemplo.
Passo 1) Crie uma classe. Neste exemplo, vamos inserir dois números usando o método sum(int, int), que retornará a soma dos números fornecidos.
Passo 2) Crie uma classe de teste parametrizada.
Code Explicação
- Code Linha 11: Anote sua classe de teste usando @RunWith(Parameterized.class).
- Code Linha 13: Declarar a variável 'firstNumber' como privada e digitar como int.
- Code Linha 14: Declarando a variável 'secondNumber' como privada e do tipo int.
- Code Linha 15: Declarando a variável 'expectedResult' como privada e do tipo int.
- Code Linha 16: Declarando a variável 'airthematic' como privada e do tipo Airthematic.
@Correr com(nome_da_classe.classe): o @Correr com A anotação é usada para especificar o nome da classe do executor. Se não especificarmos nenhum tipo como parâmetro, o ambiente de execução escolherá. BloquearJUnit4ClassRunner por padrão.
Esta classe é responsável por executar os testes com uma nova instância de teste. Ela é responsável por invocar... JUnit métodos de ciclo de vida, como configuração (associar recursos) e desmontagem (liberar recursos), que são descritos no JUnit dispositivo de teste tutorial.
Para parametrizar, você precisa anotar a classe usando @RunWith e passar o arquivo .class necessário para ser testado.
Passo 3) Crie um construtor que armazene os dados de teste. Ele armazena 3 variáveis.
Passo 4) Crie um método estático que gere e retorne dados de teste.
Code Linha 32,33: Criando uma matriz bidimensional (fornecendo parâmetros de entrada para adição). Usando o método `asList`, convertemos os dados em um tipo `List`, já que o tipo de retorno do método de entrada é uma `Collection`.
Code Linha 30: Com o @Parâmetros anotação para criar um conjunto de dados de entrada para executar nosso teste.
O método estático identificado pela anotação @Parameters retorna uma Collection onde cada entrada na Collection será o dado de entrada para uma iteração do teste. Considere o elemento {1,2,3}. Aqui:
- primeiroNúmero = 1
- segundoNúmero = 2
- resultadoEsperado = 3
Aqui, cada elemento do array será passado para o construtor, um de cada vez, à medida que a classe for instanciada várias vezes. Os cinco arrays declarados no exemplo, portanto, produzem as seguintes cinco execuções:
| Iteração | primeiroNúmero | segundoNúmero | resultado esperado | Linha de console |
|---|---|---|---|---|
| 1 | 2 | 3 | Soma de Numbers = : 3 | |
| 11 | 22 | 33 | Soma de Numbers = : 33 | |
| 111 | 222 | 333 | Soma de Numbers = : 333 | |
| 10 | 9 | 19 | Soma de Numbers = : 19 | |
| 100 | 9 | 109 | Soma de Numbers = : 109 |
Passo 5) O código completo.
Code Explicação:
- Code Linha 25: Utilizando a anotação `@Before` para configurar os recursos (Airthematic.class neste caso). A anotação `@Before` é usada aqui para ser executada antes de cada caso de teste. Ela contém a pré-condição do teste.
- Code Linha 36: Utilizando a anotação @Test para criar nosso teste.
- Code Linha 39: Criando um declaração assert para verificar se nossa soma é equivalente ao que esperávamos.
Passo 6) Crie uma classe de execução de testes para executar o teste parametrizado:
Code Explicação:
- Code Linha 8: Declarando o método principal da classe Test que executará nosso JUnit teste.
- Code Linha 9: Executando casos de teste usando JUnitCore.runClasses, que recebe o nome da classe de teste como parâmetro (em nosso exemplo, estamos usando AirthematicTest.class).
- Code Linha 11: Processando o resultado usando um laço `for` e imprimindo o resultado com falha.
- Code Linha 13: Imprimindo o resultado bem-sucedido.
Saída:
Aqui está o resultado, que mostra um teste bem-sucedido, sem falhas. trace, conforme indicado abaixo. Observe que o JUnit A visualização lista uma entrada por linha de dados em vez de um único teste:
Veja o resultado no console, que mostra a soma dos dois números:
Testes parametrizados em JUnit 5 com @ParameterizedTest
O exemplo acima foi escrito para JUnit 4. JUnit A versão 5 (Jupiter) abandona completamente o modelo de executor, portanto, o `@RunWith(Parameterized.class)`, o construtor de dados e os campos de instância desaparecem. JUnit O código 4 mostrado acima não está obsoleto: ele ainda funciona sem alterações no JUnit Plataforma através do mecanismo clássico. Novos testes, no entanto, são normalmente escritos com @ParameterizedTest.
São necessárias duas dependências: junit-jupiter-api para as anotações de teste e junit-jupiter-params para o suporte parametrizado. Sem o segundo artefato, as anotações de origem não serão resolvidas.
import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; class AirthematicTest { // one row per iteration, no constructor and no runner @ParameterizedTest(name = "{0} + {1} = {2}") @CsvSource({"1, 2, 3", "11, 22, 33", "111, 222, 333", "10, 9, 19", "100, 9, 109"}) void sumOfTwoNumbers(int firstNumber, int secondNumber, int expectedResult) { assertEquals(expectedResult, new Airthematic().sum(firstNumber, secondNumber)); } }
Júpiter oferece diversas fontes de argumentos, e a mais adequada depende do formato dos dados:
| Anotação de origem | Abastecimento | Use-o quando |
|---|---|---|
| @ValueSource | Uma única coluna de literais | O teste aceita exatamente um argumento. |
| @CsvSource | Linhas separadas por vírgulas em linha | Pequenas tabelas de números e strings são lidas sem problemas no arquivo. |
| @CsvFileSource | Linhas lidas de um arquivo CSV no classpath de teste | O conjunto de dados é grande ou mantido fora do código. |
| @MethodSource | Uma fábrica estática que retorna um fluxo de argumentos. | São necessários objetos reais, valores calculados ou dados aleatórios. |
| @EnumSource | As constantes de uma enumeração | Cada valor de enumeração deve ser exercitado. |
Duas regras costumam pegar os iniciantes desprevenidos. Uma anotação de origem colocada em um método `@Test` simples é ignorada silenciosamente, então o método deve conter `@ParameterizedTest`. E um valor vazio sem aspas em `@CsvSource` é lido como nulo, enquanto um valor vazio entre aspas é lido como uma string vazia.
O JUnit As 4 anotações usadas neste artigo são mapeadas no Jupiter da seguinte forma: `@RunWith(Parameterized.class)` torna-se `@ParameterizedTest` mais uma anotação de origem, `@Parameters` torna-se `@MethodSource` ou `@CsvSource`, e `@Before` torna-se `@BeforeEach`. A lista completa está disponível no [link para o artigo]. JUnit anotações tutorial.
Vantagens e limitações dos testes parametrizados
A parametrização não é gratuita. Ela elimina a duplicação, mas também restringe a forma como um teste pode ser escrito, portanto, vale a pena conhecer ambos os lados antes de converter um conjunto de testes existente.
Vantagens
- Less duplicação: Um dos métodos substitui um bloco de instruções assert quase idênticas, como mostra a primeira captura de tela deste artigo.
- Cobertura mais barata: Adicionar um caso extremo custa uma linha de dados a mais em vez de uma linha completamente nova. caso de teste método.
- Relatórios precisos: Cada iteração é relatada separadamente, então o JUnit A visualização identifica exatamente qual linha apresentou falha, em vez de uma falha agregada.
- Dados centralizados: Os dados de entrada residem em um único método e podem ser posteriormente movidos para um arquivo CSV ou um factory sem alterar as asserções.
Limitações
- Uma forma de afirmação: Cada linha executa as mesmas verificações, portanto, um cenário que precise de verificações diferentes ainda precisará de seu próprio método de teste.
- Escopo de nível de classe em JUnit 4: O executor parametriza a classe inteira, portanto, métodos @Test não relacionados nessa classe também são executados uma vez por linha.
- Relatórios ilegíveis: Sem um modelo de nome, as falhas aparecem como testAirthematicTest[3], que não diz nada sobre os dados que falharam.
- Dados embutidos volumosos: Grandes arrays podem sobrecarregar a lógica de teste; mova-os para uma fábrica com a anotação `@CsvFileSource` ou `@MethodSource`.
Erros comuns em JUnit Testes parametrizados
A maioria das falhas parametrizadas são erros de inicialização que ocorrem antes da execução de uma única asserção. A tabela abaixo lista as mensagens que aparecem com mais frequência e o que as desencadeia.
| Mensagem | Causar | Fixar |
|---|---|---|
| A classe de teste deve ter exatamente um construtor público. | A classe não declara nenhum construtor público, ou declara dois. | Mantenha um construtor público cujos parâmetros correspondam às colunas de dados. |
| Não existe um método público de parâmetros estáticos na classe. | O método @Parameters não é público estático ou retorna um tipo incorreto. | Declare-a como uma coleção pública estática e retorne Arrays.asList(…) |
| IllegalArgumentException: número incorreto de argumentos | Uma linha é mais larga ou mais estreita do que a lista de parâmetros do construtor. | Faça com que todos os arrays da Coleção tenham a mesma largura que o construtor. |
| Erro de configuração: nenhum provedor de argumentos | Um teste Jupiter carrega @ParameterizedTest sem nenhuma anotação de origem. | Adicione @ValueSource, @CsvSource, @CsvFileSource, @MethodSource ou @EnumSource. |
| A anotação da fonte parece não fazer nada. | O método está anotado com @Test em vez de @ParameterizedTest. | Substitua @Test por @ParameterizedTest e importe junit-jupiter-params. |
Outra armadilha é o estado compartilhado. Porque JUnit Constrói uma nova instância por linha, qualquer valor armazenado em um campo estático persiste em todas as iterações e um valor escrito pela linha [0] pode alterar silenciosamente o resultado da linha [4]. Mantenha o estado por linha nos campos da instância e redefina os recursos compartilhados no método @Before ou @BeforeEach. Orientações gerais sobre como isolar testes são abordadas em teste de unidade tutorial.









