Getting Started with JUnit 5 Testing in Micronaut
Micronaut makes testing Java applications straightforward with native JUnit 5 integration. Its lightweight dependency injection, embedded server support, and simple mocking allow us to write fast unit and integration tests with minimal setup. In this article, we’ll cover how to configure JUnit 5 in a Micronaut project and demonstrate test cases for services and controllers.
1. Adding JUnit 5 to a Project
To enable JUnit 5 testing in Micronaut, include the Micronaut JUnit 5 testing module. Additionally, if we plan to use Mockito for mocking beans in our tests, we need to include the Mockito library in our test dependencies.
<dependency>
<groupId>io.micronaut.test</groupId>
<artifactId>micronaut-test-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
In addition to the dependencies, Maven projects must configure the Surefire plugin to use the JUnit platform:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.3</version>
<configuration>
<useModulePath>false</useModulePath>
</configuration>
</plugin>
</plugins>
</build>
This setup ensures that Micronaut can properly start the test application context, JUnit 5 tests run correctly, and Mockito can be used for mocking dependencies.
If your project already includes JUnit 5 libraries, you still need to add the Micronaut JUnit 5 testing module so that the
@MicronautTest annotation functions correctly. Without this dependency, Micronaut won’t be able to start the test application context, even if JUnit 5 is present.2. A Simple Component to Test
Let’s start with a small service that returns a greeting message.
@Singleton
public class GreetingService {
public String greet(String name) {
return "Hello " + name;
}
}
This service is a Micronaut-managed bean that will be injected into the test through the application context.
3. Writing a Basic JUnit 5 Test
Micronaut provides the @MicronautTest annotation, which boots a lightweight application context and allows dependency injection directly into your test class.
@MicronautTest
class GreetingServiceTest {
@Inject
GreetingService greetingService;
@Test
void testGreeting() {
String result = greetingService.greet("Micronaut");
assertEquals("Hello Micronaut", result);
}
}
In this test, @MicronautTest starts a lightweight application context for the test class, allowing Micronaut to manage and inject beans. The @Inject annotation provides an instance of GreetingService directly to the test, and the test itself verifies the expected behaviour using standard JUnit 5 assertions. For simple scenarios, no manual wiring or mocking is necessary, since Micronaut handles dependency setup automatically.
4. Testing a REST Endpoint
Micronaut also makes it easy to test controllers using an embedded server and HTTP client.
Controller Example
@Controller("/greet")
public class GreetingController {
private final GreetingService greetingService;
public GreetingController(GreetingService greetingService) {
this.greetingService = greetingService;
}
@Get("/{name}")
public String greet(String name) {
return greetingService.greet(name);
}
}
Controller Test Using Embedded Server
@MicronautTest
class GreetingControllerTest {
@Inject
@Client("/")
HttpClient client;
@Test
void testGreetEndpoint() {
String response = client.toBlocking().retrieve("/greet/Thomas");
assertEquals("Hello Thomas", response);
}
}
With this setup, Micronaut automatically starts an embedded HTTP server for the test and injects an HTTP client using the @Client("/") annotation. This allows the test to send real HTTP requests through the application without relying on external services, closely mirroring runtime behaviour while remaining fast, lightweight, and fully isolated.
5. Using @MockBean to Replace Dependencies
When testing larger applications, we often want to isolate components and avoid calling real external services such as databases, APIs, or message brokers. Micronaut provides the @MockBean annotation to replace real beans with mocks during tests.
Assume we want to mock GreetingService in a controller test.
@MicronautTest
class GreetingControllerMockTest {
@Inject
@Client("/")
HttpClient client;
@Test
void endpointUsesMockedService() {
String response = client.toBlocking().retrieve("/greet/Thomas");
assertEquals("Mock Hello Thomas", response);
}
@MockBean(GreetingService.class)
GreetingService mockGreetingService() {
GreetingService mock = mock(GreetingService.class);
when(mock.greet("Thomas")).thenReturn("Mock Hello Thomas");
return mock;
}
}
When @MockBean(GreetingService.class) is used, Micronaut replaces the real GreetingService bean with a Mockito-generated mock provided by the annotated method. This mock is injected wherever GreetingService is required during the test, allowing us to fully control its behaviour and verify interactions. As a result, tests remain fast, predictable, and isolated from external systems
6. Conclusion
In this article, we explore how to test Micronaut applications using JUnit 5. The article presented how to configure testing, inject beans into tests, validate services and controllers, and replace real dependencies using @MockBean. Micronaut’s lightweight runtime and compile-time dependency injection make tests fast, reliable, and easy to maintain, helping us build confident and production-ready applications.
7. Download the Source Code
This article covers how to test Java Micronaut applications using JUnit5.
You can download the full source code of this example here: java micronaut junit5

