Back to Quarkus

Writing Tests

.agents/skills/writing-tests/SKILL.md

3.36.0.CR13.7 KB
Original Source

Writing Tests

Quarkus uses JUnit 5 with custom extensions. Tests and documentation are mandatory for contributions.

Test Annotations

  • @QuarkusTest — Starts a full Quarkus application. Use for integration tests in integration-tests/.
  • @QuarkusIntegrationTest — Tests against a built artifact (JAR or native binary). In the main repo, most run only with -Dnative.

Test Extensions (used with @RegisterExtension)

  • QuarkusExtensionTest — Used in deployment module tests. Creates a synthetic application defined in the test. This is the primary way to test build-time behavior. Replaces the deprecated QuarkusUnitTest.
  • QuarkusDevModeTest — Tests hot reload / dev mode behavior.

Test Location

  • Extension tests for deployment logic: extensions/<name>/deployment/src/test/
  • Integration tests needing a running app: integration-tests/
  • Deployment module tests use QuarkusExtensionTest, NOT @QuarkusTest

QuarkusExtensionTest Pattern

java
@RegisterExtension
static final QuarkusExtensionTest config = new QuarkusExtensionTest()
    .withApplicationRoot((jar) -> jar
        .addClasses(MyResource.class, MyService.class));

@Test
void testFeature() {
    // test with RestAssured or similar
}

If the tests have to set Quarkus configuration, then using QuarkusExtensionTest#overrideConfigKey for build time configuration and QuarkusExtensionTest#overrideRuntimeConfigKey for runtime configuration is preferable.

Running Tests

bash
# Run tests for an extension
./mvnw verify -f extensions/<name>/

# Run a single test class
./mvnw test -f integration-tests/<name>/ -Dtest=MyTest

# Run a single test method
./mvnw verify -Dtest=fully.qualified.ClassName#methodName

# Native integration tests
./mvnw verify -f integration-tests/<name>/ -Dnative

Native Test Registration

Native tests are split into parallel categories for CI performance. Each new integration test module must be registered in .github/native-tests.json to have its native tests run in CI. Without this, -Dnative tests will not execute for the module.

Note: @QuarkusIntegrationTest tests in the main repo only run when -Dnative is passed — even verify with -DskipITs=false will not trigger them.

MicroProfile TCK Tests

The tcks/ module contains MicroProfile TCK tests (Config, JWT, Fault Tolerance, Health, Metrics, OpenAPI, Telemetry, REST Client, Reactive Messaging, Context Propagation). If your work touches any of these areas, run the TCKs:

bash
# Run all TCKs
./mvnw verify -f tcks/ -Ptcks

# Run a specific TCK
./mvnw verify -f tcks/<area>/ -Ptcks

Assertions

  • Prefer AssertJ (org.assertj.core.api.Assertions.assertThat) over JUnit 5 assertions (org.junit.jupiter.api.Assertions). AssertJ provides fluent, readable assertions and better failure messages.
  • Use RestAssured for HTTP endpoint testing.

Key Rules

  • Do NOT use @QuarkusTest in deployment module tests — use QuarkusExtensionTest
  • Integration tests belong in integration-tests/, not in extension modules
  • Use RestAssured for HTTP endpoint testing
  • Test in both JVM and native mode for non-trivial changes
  • New native tests must be registered in .github/native-tests.json
  • Verify that build-time errors produce clear, actionable error messages
  • Container engine (Docker/Podman) is needed for dev-services tests
  • Parallel test execution is not supported
  • When writing a test that verifies a bug has been fixed, ensure that the test has run against the code that does not contain the fix and verify this test fails. This provides some confidence that the test does actually verify the fix; in other words, this addresses the never trust a test you haven't seen fail adage