This episode covers testing in Quarkus: unit testing with JUnit 5, integration testing with @QuarkusTest, mocking and REST client testing, as well as Testcontainers and end-to-end testing.

An application without tests is a latent danger: one small change can break a feature unnoticed until users complain. Quarkus has first-class testing support — from plain unit tests to integration tests that run the full application.
Episode 17 covers testing and quality assurance in Quarkus: unit testing with JUnit 5, integration testing with @QuarkusTest, mocking and REST client testing, as well as Testcontainers and end-to-end testing.
Quarkus automatically includes the testing dependencies in a new project. A plain JUnit 5 unit test for a service:
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class GreetingServiceTest {
GreetingService service = new GreetingService();
@Test
void testSapa() {
assertEquals("Halo, Quarkus!", service.sapa("Quarkus"));
}
}This test is purely unit: it doesn't run Quarkus, only tests the class logic. Fast and focused.
./mvnw testThe command ./mvnw test runs all tests. In a Quarkus project, tests automatically run in the test profile.
@QuarkusTest runs the actual Quarkus application — the CDI container is active, endpoints are available, and you can test end-to-end within the JVM:
import io.quarkus.test.junit.QuarkusTest;
import io.restassured.RestAssured;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.is;
@QuarkusTest
public class GreetingResourceTest {
@Test
void testHello() {
given()
.when().get("/hello")
.then()
.statusCode(200)
.body(is("Halo Quarkus!"));
}
}This test starts a real application on a random port, sends HTTP requests with REST Assured, and verifies the status and body. @QuarkusTest is the most common way to test endpoints in Quarkus.
Because the container is active, you can @Inject beans directly in the test and verify them with assertNotNull(service) — no extra setup.
To replace dependencies in an integration test, use @InjectMock:
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.junit.mockito.InjectMock;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import static io.restassured.RestAssured.given;
@QuarkusTest
public class GreetingMockTest {
@InjectMock
GreetingService greetingService;
@Test
void testDenganMock() {
Mockito.when(greetingService.sapa("Quarkus"))
.thenReturn("Halo dari mock");
given().when().get("/hello")
.then().statusCode(200);
}
}@InjectMock replaces the GreetingService bean in the container with a mock. This is very useful for isolating a resource from external dependencies.
A REST client (episode 14) can also be tested: inject the client with @RestClient, call its method, and verify the result with assertEquals(...). If the external service isn't available, mock the client with @InjectMock and @RestClient.
For tests involving a database, use Testcontainers to run a real database in a container. Add the quarkus-test-h2 dependency with the test scope; for PostgreSQL use quarkus-test-postgresql or Testcontainers directly with @QuarkusTestResource.
import io.quarkus.test.common.QuarkusTestResource;
import io.quarkus.test.junit.QuarkusTest;
@QuarkusTest
@QuarkusTestResource(PostgresTestResource.class)
public class OrderRepositoryTest {
// the test uses PostgreSQL running in a container
}@QuarkusTestResource activates the Testcontainers resource during the test. A real database gives higher confidence than in-memory H2 for behavior that depends on database-specific features.
For slow tests like native images, separate them with a JUnit profile: tag them with @Tag("e2e") and run only e2e tests with ./mvnw test -Dgroups=e2e in a separate pipeline so they don't slow down the daily development loop.
Episode 17 builds your quality safety net: unit testing with JUnit 5, integration testing with @QuarkusTest which runs a real application, mocking with @InjectMock and REST client testing, as well as Testcontainers and end-to-end testing for full confidence.
Key takeaways:
@QuarkusTest runs a real application for integration testing.@InjectMock replaces beans with mocks in the test container.@RestClient.In episode 18 we'll cover architecture and design patterns — modular architecture with feature-based organization, domain-driven design and hexagonal architecture, event-driven architecture with reactive messaging, as well as CQRS, event sourcing, and publish/subscribe patterns.