In this tutorial, we will learn how to perform Micronaut Unit testing for Controllers and Services. We will build a simple Student Management example using com.kscodes.micronaut
package structure, and then create tests using JUnit 5 and Mockito.

As you have gone through Creating REST Endpoints with @Controller and @Get/@Post, lets see how Micronaut Unit testing for this is done.
Project Setup
We will create a simple Student Management system where we can:
- Add a new student
- Retrieve student details
Dependencies
In your pom.xml
, make sure you have these dependencies:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<dependencies> <!-- Micronaut Dependencies --> <dependency> <groupid>io.micronaut</groupid> <artifactid>micronaut-inject</artifactid> </dependency> <dependency> <groupid>io.micronaut</groupid> <artifactid>micronaut-http-client</artifactid> </dependency> <!-- JUnit 5 --> <dependency> <groupid>org.junit.jupiter</groupid> <artifactid>junit-jupiter-engine</artifactid> <scope>test</scope> </dependency> <!-- Mockito --> <dependency> <groupid>org.mockito</groupid> <artifactid>mockito-core</artifactid> <scope>test</scope> </dependency> <!-- Micronaut Test --> <dependency> <groupid>io.micronaut.test</groupid> <artifactid>micronaut-test-junit5</artifactid> <scope>test</scope> </dependency> </dependencies> |
Create the Application Code
Student Model
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
package com.kscodes.micronaut.model; public class Student { private String id; private String name; public Student(String id, String name) { this.id = id; this.name = name; } public String getId() { return id; } public String getName() { return name; } } |
StudentService
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
package com.kscodes.micronaut.service; import com.kscodes.micronaut.model.Student; import jakarta.inject.Singleton; import java.util.HashMap; import java.util.Map; import java.util.Optional; @Singleton public class StudentService { private final Map<String, Student> students = new HashMap<>(); public void addStudent(Student student) { students.put(student.getId(), student); } public Optional<Student> getStudent(String id) { return Optional.ofNullable(students.get(id)); } } |
StudentController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
package com.kscodes.micronaut.controller; import com.kscodes.micronaut.model.Student; import com.kscodes.micronaut.service.StudentService; import io.micronaut.http.HttpResponse; import io.micronaut.http.annotation.*; import jakarta.inject.Inject; import java.util.Optional; @Controller("/students") public class StudentController { @Inject private StudentService studentService; @Post public HttpResponse<String> addStudent(@Body Student student) { studentService.addStudent(student); return HttpResponse.ok("Student added successfully"); } @Get("/{id}") public HttpResponse<Student> getStudent(@PathVariable String id) { Optional<Student> student = studentService.getStudent(id); return student.map(HttpResponse::ok) .orElseGet(() -> HttpResponse.notFound()); } } |
Unit Testing the Service
Since StudentService
is simple and has no external dependencies, we can write pure unit tests.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
package com.kscodes.micronaut.service; import com.kscodes.micronaut.model.Student; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; public class StudentServiceTest { @Test public void testAddAndGetStudent() { StudentService service = new StudentService(); Student student = new Student("1", "John Doe"); service.addStudent(student); Assertions.assertTrue(service.getStudent("1").isPresent()); Assertions.assertEquals("John Doe", service.getStudent("1").get().getName()); } @Test public void testGetStudentNotFound() { StudentService service = new StudentService(); Assertions.assertFalse(service.getStudent("unknown").isPresent()); } } |
Unit Testing the Controller
For the controller, we mock the StudentService
dependency.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
package com.kscodes.micronaut.controller; import com.kscodes.micronaut.model.Student; import com.kscodes.micronaut.service.StudentService; import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import jakarta.inject.Inject; import org.junit.jupiter.api.Test; import org.mockito.Mockito; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.InjectMocks; import org.mockito.Mock; import io.micronaut.http.HttpResponse; import java.util.Optional; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) public class StudentControllerTest { @Mock StudentService studentService; @InjectMocks StudentController studentController; @Test public void testAddStudent() { Student student = new Student("1", "John Doe"); HttpResponse<String> response = studentController.addStudent(student); verify(studentService, times(1)).addStudent(student); assertEquals(200, response.getStatus().getCode()); assertEquals("Student added successfully", response.body()); } @Test public void testGetStudentFound() { Student student = new Student("1", "John Doe"); when(studentService.getStudent("1")).thenReturn(Optional.of(student)); HttpResponse<Student> response = studentController.getStudent("1"); assertEquals(200, response.getStatus().getCode()); assertEquals("John Doe", response.body().getName()); } @Test public void testGetStudentNotFound() { when(studentService.getStudent("2")).thenReturn(Optional.empty()); HttpResponse<Student> response = studentController.getStudent("2"); assertEquals(404, response.getStatus().getCode()); } } |
Summary
- Use pure unit tests for services with no dependencies.
- Use mocks (e.g. Mockito) to isolate controller tests from the service layer.
- Micronaut makes testing simple with its dependency injection and fast startup time.