JUnit 5 e Testes Parametrizados: Testando Benefícios com Elegância
Em sistemas de benefícios, uma transação pode passar ou falhar por dezenas de motivos: saldo insuficiente, categoria errada, cartão bloqueado, limite diário excedido, etc. Se você escrever um método de teste para cada cenário, seu arquivo de teste terá 2000 linhas. O @ParameterizedTest do JUnit 5 é o seu melhor amigo.
O Código Repetitivo
Você já se viu copiando e colando o mesmo teste, mudando apenas um valor e o resultado esperado? Isso é um sinal de que você deve usar testes parametrizados.
Exemplo Prático: Validação de Categorias
Imagine que queremos testar se o cartão de benefícios aceita o estabelecimento baseado no código de categoria (MCC).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class MerchantValidationTest {
@ParameterizedTest
@CsvSource({
"5812, MEAL, true", // Restaurante no benefício Refeição
"5411, FOOD, true", // Supermercado no benefício Alimentação
"5812, FOOD, false", // Restaurante NÃO passa no Alimentação pura
"5000, MEAL, false" // Loja de Ferragens NÃO passa no Refeição
})
void shouldValidateMerchantCategory(int mcc, Category category, boolean expectedResult) {
boolean result = validator.isValid(mcc, category);
assertEquals(expectedResult, result);
}
}
Fontes de Dados (Sources)
O JUnit 5 oferece várias formas de injetar dados:
- @ValueSource: Para uma lista simples de strings ou números.
- @CsvSource: Para múltiplos parâmetros (como o exemplo acima).
- @MethodSource: Para cenários complexos onde você precisa de uma função que retorne uma lista de objetos.
Por que isso é bom?
- Manutenibilidade: Se a regra de negócio mudar, você altera apenas uma linha na tabela de dados, não o código do teste.
- Cobertura: Facilita testar “Edge Cases” (casos de borda) que você poderia esquecer se tivesse que escrever um teste completo para cada um.
- Legibilidade: O nome do teste no relatório fica claro:
shouldValidateMerchantCategory[1] mcc=5812, category=MEAL -> true.
Exemplo final: O poder do @MethodSource
Para fechar, imagine que você precisa validar objetos complexos. Com o @MethodSource, você pode passar instâncias inteiras de classes de domínio para o seu teste:
1
2
3
4
5
6
7
8
9
10
11
12
static Stream<Arguments> provideTransactions() {
return Stream.of(
Arguments.of(new Transaction(100, Category.MEAL), true),
Arguments.of(new Transaction(5000, Category.MEAL), false) // Excedeu limite
);
}
@ParameterizedTest
@MethodSource("provideTransactions")
void testComplexTransaction(Transaction tx, boolean expected) {
assertEquals(expected, engine.process(tx));
}
Essa flexibilidade permite que sua suíte de testes acompanhe a evolução de qualquer regra de negócio, por mais complexa que ela seja.