Backend Testing
Functionality required by the "Pflichtenheft" must be tested.
Spring Boot Controller Testing
Scope
We only test at the controller layer, verifying the correct HTTP behavior, request/response mapping, validation, and controller-service interaction. (→ Blackbox-Testing)
No mocking of the controller, but mocking/stubbing of lower layers (e.g., services or repositories) is allowed when needed.
Default Tools
- Spring Boot Test (
@SpringBootTest
) – for full application context tests (optional, slower). - @WebMvcTest – for isolated controller tests (recommended for speed and focus).
- MockMvc – to simulate HTTP requests to the controller.
- Mockito – for mocking services under the controller.
- AssertJ / Hamcrest – for fluent assertions.
- JUnit 5 – as default test engine.
Testing Approach
- Use
@WebMvcTest(YourController.class)
to load only the web layer. - Inject
MockMvc
to perform requests. - Mock external services (e.g., service layer beans) with
@MockBean
. - Cover at least:
- Request mapping
- Validation rules
- Expected response codes and JSON bodies
Example Controller Test
Let's say we have this simple controller:
@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/{id}")
public ResponseEntity<UserDto> getUser(@PathVariable Long id) {
return ResponseEntity.ok(userService.getUserById(id));
}
}
Here’s a corresponding controller test: (this file should lay inside src/test/java/com/agilesoftwareengineering/[your-application]/UserControllerTest.class
)
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@Test
void shouldReturnUserById() throws Exception {
UserDto user = new UserDto(1L, "Alice");
Mockito.when(userService.getUserById(1L)).thenReturn(user);
mockMvc.perform(get("/api/users/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value(1))
.andExpect(jsonPath("$.name").value("Alice"));
}
}
Notes
- Stick to controller-only logic (i.e., no testing service/repo logic here).
- Run these tests on every merge or pull request.
- Consider using Testcontainers if you eventually expand to integration testing (e.g., testing DB + controller together).