Um dos atributos de qualidade de um teste automatizado é o tamanho da amostra exercitada nos testes.
Um exemplo de um teste simples, mas com amostragem baixa, pode ser mostrado com o seguinte código:
@Test
void verifySumOfTwoIntegersIsAlwaysPositive() {
int umPositivo = 1;
int outroPositivo = 2;
assertThat(umPositivo).isPositive();
assertThat(outroPositivo).isPositive();
assertThat(Integer.sum(umPositivo, outroPositivo))
.isPositive();
}
Um teste simples que verifica a assertividade da soma pode ser um teste incompleto e falho.
Se usarmos outros dados no teste, por exemplo:
@Test
void failingTest() {
int umPositivo = 1;
int outroPositivo = 1 + Integer.MAX_VALUE;
assertThat(umPositivo + Integer.MAX_VALUE).isPositive();
assertThat(outroPositivo).isPositive();
assertThat(Integer.sum(umPositivo, outroPositivo))
.isPositive();
}
O teste falha, pois ocorre um overflow numérico na soma, que se torna negativa.
Um exemplo simples como este mostra a importância de termos dados e amostras suficientes exercitados nos testes para nos sentirmos mais confiantes sobre o código que estamos testando.
Mas este trabalho nem sempre é simples e exige esforço.
E é aí que entra o Instancio! Ele é uma ferramenta que pode simplificar e facilitar este trabalho.
Irei apresentar dois pontos que, na minha opinião, são interessantes para adotar em um projeto Java/Spring!
🛠️ Facilidade de criar a massa de dados#
Imagine que temos uma entidade com JPA/Hibernate abaixo:
package br.com.youready.article.d_2026_01_04;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.hibernate.validator.constraints.br.CPF;
@Entity
@Getter
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class PessoaFisica {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
@NotBlank
private String name;
@Email
private String email;
@CPF
private String cpf;
public static PessoaFisica comEmail(String email) {
PessoaFisica pessoaFisica = new PessoaFisica();
pessoaFisica.email = email;
return pessoaFisica;
}
}
Criar o objeto manualmente e definir cada propriedade com valor apropriado exige esforço. O Instancio facilita este trabalho gerando valores aleatórios para cada campo automaticamente.
Abaixo mostro algumas das principais funcionalidades que ele oferece.
Criação de objetos simples#
A forma mais básica de uso. Com uma única linha, você tem um objeto totalmente populado com dados aleatórios, sem campos nulos.
@Test
void simpleObjectCreationExample() {
// Por padrão, todos os campos são populados com dados aleatórios!
PessoaFisica pessoaFisicaParaTeste = Instancio.create(PessoaFisica.class);
assertThat(pessoaFisicaParaTeste).hasNoNullFieldsOrProperties();
// Exemplo de saída: pessoaFisicaParaTeste = PessoaFisica(id=7317, name=GDFVO, email=QJV, cpf=ACMOSMKKYB)
System.out.println("pessoaFisicaParaTeste = " + pessoaFisicaParaTeste);
}
@Test
Criando Listas#
Precisa de uma lista para testar um fluxo de coleção? O Instancio cria listas com tamanho definido ou aleatório num piscar de olhos.
// Se não especificar o tamanho, ele cria uma lista de tamanho aleatório entre 2 e 6 elementos
List<PessoaFisica> listaDePF = Instancio.ofList(PessoaFisica.class)
.size(3)
.create();
assertThat(listaDePF).hasSize(3)
.allSatisfy(pessoaFisica -> assertThat(pessoaFisica).hasNoNullFieldsOrProperties());
// Exemplo de saída: [PessoaFisica(id=3373, name=LEUQQSPPR, email=ZJHSDAVXVI, cpf=SYHZ),
// PessoaFisica(id=3724, name=ZZMIOSBKN, email=SXFXOF, cpf=CWEKYSUFQX),
// PessoaFisica(id=8790, name=MRMMR, email=PAAAD, cpf=RGOTNDXWF)]
System.out.println("listaDePF = " + listaDePF);
}
@Test
void populateOtherMandatoryFields() {
String emailParaTeste = "teste@teste.com.br";
// É possível popular o objeto após a definição de alguns dados
PessoaFisica pessoaFisica = PessoaFisica.comEmail(emailParaTeste);
Populando objetos existentes#
Se você já tem um objeto parcialmente criado (com dados específicos para o teste) e quer preencher o restante, use o fill.
assertThat(pessoaFisica)
.hasNoNullFieldsOrProperties()
.extracting(PessoaFisica::getEmail)
.isEqualTo(emailParaTeste);
// Exemplo de saída: PessoaFisica(id=6265, name=BMDJDFGYH, email=teste@teste.com.br, cpf=EZPQVB)
System.out.println("pessoaFisica = " + pessoaFisica);
}
@Test
void useJakartaOrHibernateContraints() {
// Instancio suporta:
// jakarta.validation.constraints
// javax.validation.constraints
// org.hibernate.validator.constraints
PessoaFisica pessoaFisica = Instancio.of(PessoaFisica.class)
Suporte a Bean Validation#
O Instancio entende anotações do Jakarta Validation (@NotNull, @Email, @CPF, etc.) e gera dados válidos que respeitam essas restrições. Basta habilitar nas configurações.
.withSetting(Keys.JPA_ENABLED, true)
.create();
assertThat(pessoaFisica).hasNoNullFieldsOrProperties();
// Exemplo de saída: PessoaFisica(id=5966, name=MFARYO, email=7hw1@wy.org, cpf=41474030777)
// Observe que foi gerado um email e cpf válido aleatório.
System.out.println("pessoaFisica = " + pessoaFisica);
}
@Test
void useGenerator() {
// É possível gerar os valores dos campos de acordo com a sua necessidade
PessoaFisica pessoaFisica = Instancio.of(PessoaFisica.class)
.withSetting(Keys.BEAN_VALIDATION_ENABLED, true)
.withSetting(Keys.JPA_ENABLED, true)
.generate(Select.field(PessoaFisica::getName), generator -> generator.oneOf("Rafael", "Issao", "Thais"))
.create();
Personalizando dados#
Quando você precisa de valores específicos (como escolher um item de uma lista pré-definida), o método generate te dá controle total.
assertThat(pessoaFisica).hasNoNullFieldsOrProperties()
.extracting(PessoaFisica::getName)
.isIn("Rafael", "Issao", "Thais");
// Exemplo de saída: PessoaFisica(id=4142, name=Rafael, email=7@15z.com, cpf=38372761639)
// O 'name' vai ser um dos três valores especificados
System.out.println("pessoaFisica = " + pessoaFisica);
}
@Test
void defineAModelAndUseInAnyTest() {
// Defina o modelo e aproveite para utilizar em qualquer classe de teste que precise do objeto
Model<PessoaFisica> modeloParaPF = Instancio.of(PessoaFisica.class)
.withSetting(Keys.BEAN_VALIDATION_ENABLED, true)
.withSetting(Keys.JPA_ENABLED, true)
.generate(Select.field(PessoaFisica::getName), generator -> generator.oneOf("Rafael", "Issao", "Thais"))
.toModel();
PessoaFisica pessoaFisica = Instancio.create(modeloParaPF);
assertThat(pessoaFisica).hasNoNullFieldsOrProperties()
.extracting(PessoaFisica::getName)
.isIn("Rafael", "Issao", "Thais");
Reutilizando modelos#
Para evitar duplicação de configuração de testes, você pode definir um Model e reutilizá-lo em qualquer lugar.
}
}
E tem muito mais, confira na documentação do Instancio!
🧪 Integrado com JUnit Jupiter#
É possível utilizar o Instancio de forma integrada com JUnit Jupiter. Ele traz algumas facilidades integradas que aceleram ainda mais a escrita de testes.
Para isso, é necessário usar a extensão @ExtendWith(InstancioExtension.class).
Injeção automática (@Given)#
Esqueça a chamada manual do Instancio.create. Com @Given e @WithSettings, o objeto já chega pronto no seu teste.
import org.instancio.junit.*;
import org.instancio.settings.Keys;
import org.instancio.settings.Settings;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import static org.assertj.core.api.Assertions.assertThat;
// Anotação obrigatória para usar, por exemplo, @Given, @WithSettings, @Seed e @InstancioSource
@ExtendWith(InstancioExtension.class)
public class InstancioIntegratedWithJunitJupiterExampleTest {
@Given
PessoaFisica pessoaFisica;
// Possibilidade de configurar o Instancio na classe
@WithSettings
private static final Settings settings = Settings.create()
.set(Keys.BEAN_VALIDATION_ENABLED, true)
.set(Keys.JPA_ENABLED, true);
@Test
void noNeedToUseInstancioDirectly() {
// Injetado via @Given
assertThat(pessoaFisica).hasNoNullFieldsOrProperties();
System.out.println("pessoaFisica = " + pessoaFisica);
}
Data Driven Testing (@InstancioSource)#
O destaque vai para o @InstancioSource. Com ele conseguimos aumentar drasticamente o tamanho da amostragem de um teste. Por padrão, ele executa o teste com 100 dados aleatórios diferentes, garantindo que seu código funcione para uma ampla gama de entradas.
@ParameterizedTest
@InstancioSource
void letsUseTheRandomDataMultipleTimes(PessoaFisica pessoaFisica) {
// Data Driven Testing. 100 amostras é o valor padrão
assertThat(pessoaFisica).hasNoNullFieldsOrProperties();
System.out.println("pessoaFisica = " + pessoaFisica);
}
Reproduzindo falhas (@Seed)#
“Mas se o dado é aleatório, como eu reproduzo um erro?”
O Instancio pensou nisso. Quando um teste falha, ele imprime no console a seed (semente) usada naquela execução. Basta adicionar a anotação @Seed com esse valor e o teste rodará exatamente com os mesmos dados, permitindo o debug.
@Test
@Seed(666919272848427237L) // Esta anotação garante que será gerado os mesmos dados para facilitar o debug
void aSeedIsProvidedWhenErrorOccurs() {
// Esse teste falha com dados aleatórios, mas o instancio provê a semente utilizada para gerar os dados aleatórios:
// O texto abaixo é fornecido quando um teste falha:
// Test method 'aSeedIsProvidedWhenErrorOccurs' failed with seed: 666919272848427237 (seed source: random seed)
assertThat(pessoaFisica).hasNoNullFieldsOrProperties()
.extracting(PessoaFisica::getName)
.isEqualTo("Nome não existente");
System.out.println("pessoaFisica = " + pessoaFisica);
}
📚 Referências#
Para saber mais, recomendo a leitura dos guias oficiais:
✨ Conclusão#
Muitas vezes, a preguiça de criar massa de dados faz com que escrevamos testes viciados e com baixa cobertura de cenários.
O Instancio remove essa barreira, permitindo que foquemos no que realmente importa: o comportamento do nosso código.
Com ele, conseguimos simular cenários complexos, edge cases e garantir que nossa aplicação seja resiliente, tudo isso com poucas linhas de código e integrado ao nosso ciclo de testes com JUnit.
Se você ainda cria objetos manualmente para seus testes, dê uma chance para o Instancio. Sua bateria de testes agradecerá!
E você, já usa alguma ferramenta para gerar massa de dados? Tem alguma dica para compartilhar?
Deixe seu comentário!
🥒🥒 Até o próximo artigo! 🥒🥒


