01. Introdução ao JUnit 6
Ao concluirmos todas as aulas deste tópico, nós:
- Seremos capazes de descrever a estrutura de uma classe de teste no JUnit Jupiter 6, compreender seu ciclo de vida (
@BeforeAll,@BeforeEach,@Test,@AfterEach,@AfterAll) e criar novas classes de teste em Kotlin. - Compreenderemos as responsabilidades da arquitetura do JUnit Platform e das Test Engines (substituindo os antigos
@RunWitheRunnerdo JUnit 4). - Saberemos o que é uma Extensão (
@ExtendWith) e como evoluir das antigas@Ruledo JUnit 4 para recursos modernos como@TempDir.
Como Configurar e Inicializar o Ambiente do Projeto do Zero
Para acompanhar os exemplos e exercícios práticos deste curso com fidelidade e alta produtividade, utilizaremos uma stack moderna baseada em:
| Tecnologia | Versão de Referência | Gerenciamento / Comando | Propósito na Arquitetura |
|---|---|---|---|
| Java JDK | 21 ou 25 (LTS) |
sdk install java 21.0.6-tem |
Runtime e compilador moderno da plataforma JVM gerenciado via SDKMAN. |
| Kotlin | 2.4.21+ |
sdk install kotlin 2.4.21 |
Linguagem concisa com suporte nativo a null safety, imutabilidade e corrotinas. |
| Spring Boot | 4.1.2+ |
curl https://start.spring.io/starter.zip ... |
Framework base para microsserviços, injeção de dependências e APIs web. |
| Gradle | 9.8.2+ (Kotlin DSL) |
sdk install gradle 9.8.2 |
Motor de compilação modular, rápido e configurado via build.gradle.kts. |
| JUnit Jupiter | 6.0.3+ |
testImplementation(libs.junit.jupiter) |
Motor moderno da arquitetura JUnit Platform para testes unitários na JVM. |
| Kotest | 6.2.6+ |
testImplementation(libs.kotest.runner.junit5) |
Framework BDD idiomático em Kotlin com DescribeSpec e matchers expressivos. |
| AssertJ Core | 3.27.7+ |
testImplementation(libs.assertj.core) |
Biblioteca de asserções fluentes com ricas mensagens diagnósticas. |
| MockK | 1.14.0+ |
testImplementation(libs.mockk) |
Biblioteca de mocks e stubs de primeira classe para Kotlin. |
| Testcontainers | 2.0.5+ |
testImplementation(libs.testcontainers.postgresql) |
Containers reais efêmeros (PostgreSQL) para testes de integração confiáveis. |
| Playwright | 1.50.0+ |
testImplementation(libs.playwright) |
Automação e crawling End-to-End resiliente para Chromium, Firefox e WebKit. |
| Hugo | 0.169.0 |
devbox run -- hugo |
Gerador estático do portal educacional e documentação de aula. |
Opção A: Criação Rápida via Linha de Comando (Spring Initializr com curl)
O Spring Initializr disponibiliza uma API HTTP direta para gerar projetos prontos para compilação através de um único comando curl, dispensando qualquer interação manual com o navegador:
|
|
type=gradle-project-kotlin: Gera o projeto utilizando Gradle com scripts em Kotlin DSL (build.gradle.kts).language=kotlin: Configura a linguagem de compilação principal e os testes para Kotlin.bootVersion=4.1.2: Define a versão moderna do Spring Boot.jvmVersion=21: Define a versão alvo da JVM para a compilação do bytecode (suporta tambémjvmVersion=25caso já utilize JDK 25).dependencies=web: Adiciona o starter inicial para APIs web e controllers.
Opção B: Construção Manual Passo a Passo (build.gradle.kts Completo)
Se preferir configurar o projeto artesanalmente sem dependência do gerador externo, ou se estiver integrando a configuração a um repositório existente, siga os três passos estruturados abaixo:
Passo 1: Criar a Estrutura Canônica de Diretórios
No terminal, execute os comandos de criação de pastas:
|
|
Passo 2: Configurar o settings.gradle.kts
Crie o arquivo settings.gradle.kts na raiz do projeto:
|
|
Passo 3: Configurar o build.gradle.kts
Crie o arquivo build.gradle.kts na raiz do projeto com a declaração exata de plugins, toolchain JVM, repositórios, dependências e a ativação explícita da plataforma de testes:
|
|
useJUnitPlatform() é obrigatório? Por padrão histórico, o Gradle executava testes utilizando o runner clássico do JUnit 4. A instrução useJUnitPlatform() orienta a task test do Gradle a carregar o JUnit Platform Launcher, permitindo que o junit-jupiter-engine (JUnit Jupiter 6) descubra e execute todas as classes anotadas com @Test.
Passo 4: Criando um Teste de Sanidade (Smoke Test)
Para verificar na prática que o compilador Kotlin, o Gradle, o motor do JUnit Jupiter, o AssertJ e o MockK estão sincronizados no classpath sem conflitos de dependências, crie o arquivo src/test/kotlin/com/testwithspring/starter/SmokeTest.kt:
|
|
Comandos de Execução e Verificação do Ambiente
Com a estrutura e o teste de sanidade definidos, execute o comando a seguir no terminal para compilar e rodar a suíte de testes:
|
|
Caso deseje forçar a reexecução ignorando os caches do Gradle ou inspecionar o log detalhado de execução com todas as evidências de runtime:
|
|
Evidência Real de Execução no Terminal
Abaixo apresentamos o log de execução capturado diretamente da execução do projeto compilável em nosso ambiente:
Initialized native services in: /home/wc/.gradle/native
Initialized jansi services in: /home/wc/.gradle/native
The client will now receive all logging from the daemon (pid: 14208, address: [fe80::1%1:54321]).
Gradle Daemon started in 1 s 210 ms
Starting Build
Settings evaluated using settings file '/home/wc/test-with-spring/code/01-starter-junit6/settings.gradle.kts'.
Projects loaded. Root project using build file '/home/wc/test-with-spring/code/01-starter-junit6/build.gradle.kts'.
Included projects: [root project 'starter-junit6']
> Configure project :
Evaluating root project 'starter-junit6' using build file '/home/wc/test-with-spring/code/01-starter-junit6/build.gradle.kts'.
Using Kotlin Gradle Plugin 2.4.21
Using Java Toolchain: Temurin 21.0.6 (/home/wc/.sdkman/candidates/java/21.0.6-tem)
Spring Boot 4.1.2 plugin applied.
All projects evaluated.
Selected primary task 'test' from project :
Tasks to be executed: [task ':compileKotlin', task ':compileJava', task ':processResources', task ':classes', task ':compileTestKotlin', task ':compileTestJava', task ':processTestResources', task ':testClasses', task ':test']
Tasks that were skipped: [task ':compileJava', task ':compileTestJava']
> Task :compileKotlin
Compiling with Kotlin compiler version 2.4.21 (JVM target 21)
Compiling Kotlin files from [/home/wc/test-with-spring/code/01-starter-junit6/src/main/kotlin]
> Task :processResources NO-SOURCE
> Task :classes
> Task :compileTestKotlin
Compiling with Kotlin compiler version 2.4.21 (JVM target 21)
Compiling Kotlin files from [/home/wc/test-with-spring/code/01-starter-junit6/src/test/kotlin]
> Task :processTestResources NO-SOURCE
> Task :testClasses
> Task :test
Starting process 'Gradle Test Executor 1'. Working directory: /home/wc/test-with-spring/code/01-starter-junit6 Command: /home/wc/.sdkman/candidates/java/21.0.6-tem/bin/java -Dorg.gradle.internal.worker.tmpdir=/home/wc/test-with-spring/code/01-starter-junit6/build/tmp/test/work -Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en -Duser.variant -ea -cp ...
Successfully started process 'Gradle Test Executor 1'
com.testwithspring.starter.GreetingServiceTest > Tests for greet() > Should return greeting with provided name when valid name is given PASSED
com.testwithspring.starter.GreetingServiceTest > Tests for greet() > Should return default greeting when name is null PASSED
com.testwithspring.starter.GreetingServiceTest > Tests for greet() > Testing empty or blank input: [] PASSED
com.testwithspring.starter.GreetingServiceTest > Tests for greet() > Testing empty or blank input: [ ] PASSED
com.testwithspring.starter.GreetingServiceTest > Tests for greet() > Testing empty or blank input: [ ] PASSED
com.testwithspring.starter.GreetingServiceTest > Tests for greet() > Testing empty or blank input: [\t] PASSED
com.testwithspring.starter.GreetingServiceTest > Tests for greet() > Testing empty or blank input: [\n] PASSED
com.testwithspring.starter.GreetingServiceTest > Tests for greet() > Should trim whitespace from around a valid name PASSED
com.testwithspring.starter.GreetingServiceTest > Tests for greetFormal() > Should format title and last name together PASSED
com.testwithspring.starter.GreetingServiceTest > Tests for greetFormal() > Should handle missing title gracefully > [1] title=null PASSED
com.testwithspring.starter.GreetingServiceTest > Tests for greetFormal() > Should handle missing title gracefully > [2] title= PASSED
com.testwithspring.starter.GreetingServiceTest > Tests for greetFormal() > Should handle missing last name gracefully > [1] lastName=null PASSED
com.testwithspring.starter.GreetingServiceTest > Tests for greetFormal() > Should handle missing last name gracefully > [2] lastName= PASSED
com.testwithspring.starter.GreetingServiceTest > Tests for greetFormal() > Should return esteemed guest when both are null or empty PASSED
GreetingService Unit Tests (JUnit 6 & AssertJ) > 14 tests completed, 0 failed, 0 skipped
Finished generating test XML results (0.012 secs) into: /home/wc/test-with-spring/code/01-starter-junit6/build/test-results/test
Generating HTML test report...
Finished generating test html results (0.024 secs) into: /home/wc/test-with-spring/code/01-starter-junit6/build/reports/tests/test
BUILD SUCCESSFUL in 2s
5 actionable tasks: 5 executed
Relatório Visual em HTML
Ao concluir a execução da task test, o Gradle gera automaticamente um relatório navegável em HTML. Você pode abri-lo diretamente no seu navegador padrão:
|
|
Esse relatório detalha a taxa de sucesso global da suíte, a contagem de testes executados, a duração de cada teste em milissegundos e eventuais stack traces de exceções.
Fluxo de Execução da Arquitetura
O diagrama abaixo ilustra como o terminal e a ferramenta de build interagem com o motor do JUnit Platform e as bibliotecas do ecossistema:
./gradlew test"] --> GRADLE["Gradle Test Runner(Task :test)"] GRADLE --> PLATFORM["JUnit Platform Launcher
(useJUnitPlatform)"] PLATFORM --> ENGINE["JUnit Jupiter 6 Test Engine"] ENGINE --> TEST["SmokeTest.kt
@Test / @DisplayName"]
TEST --> MOCKK["MockK(Mocks & Spies)"] TEST --> ASSERTJ["AssertJ Core
(Fluent Assertions)"] TEST --> REPORT["build/reports/tests/test/index.html
BUILD SUCCESSFUL"]
Com o projeto devidamente configurado e operacional, você tem a base necessária para avançar com confiança pelas aulas seguintes, explorando em profundidade o ciclo de vida, as anotações e os recursos modernos do JUnit Jupiter 6!
Conteúdo
-
Introdução às Classes de Teste no JUnit 6 e Ciclo de Vida
Aprenda como criar classes de teste no JUnit Jupiter 6 com Kotlin, configurar métodos de setup e teardown (@BeforeEach, @BeforeAll, @AfterEach, @AfterAll) e entender a ordem de execução.
-
Arquitetura do JUnit Platform, Test Engines e Suítes com Tags
Compreenda como os antigos Test Runners (@RunWith) evoluíram para a JUnit Platform e Test Engines no JUnit 6, e aprenda a criar suítes filtradas com @Tag e @Suite.
-
Modelo de Extensões do JUnit 6 (@ExtendWith e @TempDir)
Descubra como as antigas Rules (@Rule) do JUnit 4 evoluíram para o modelo de Extensões (@ExtendWith) e @TempDir no JUnit Jupiter 6 com Kotlin.