Spring Boot Testing
Testing verifies that your code works correctly. Spring Boot includes a full testing setup — JUnit 5, Mockito, and MockMvc — with no extra configuration. Write tests early, and they protect you from breaking things later.
Testing Dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
This single starter includes JUnit 5, Mockito, AssertJ, MockMvc, and more.
Types of Tests in Spring Boot
Test Type What Gets Loaded Speed Use For ───────────────── ───────────────────── ─────── ────────────────────────── Unit test Nothing (just the class) Fastest Service, utility logic @WebMvcTest Controller + MVC layer Fast REST endpoint behavior @DataJpaTest JPA + in-memory DB Medium Repository queries @SpringBootTest Full application Slowest Integration, end-to-end
Unit Testing a Service with Mockito
A unit test checks one class in isolation. Mock its dependencies so you test only the logic in that class:
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
private UserRepository userRepository; ← Fake repository (no DB)
@InjectMocks
private UserService userService; ← Real service, fake dependencies
@Test
void findById_returnsUser_whenUserExists() {
// Arrange
User user = new User(1L, "Alice", "alice@test.com");
when(userRepository.findById(1L)).thenReturn(Optional.of(user));
// Act
User result = userService.findById(1L);
// Assert
assertThat(result.getName()).isEqualTo("Alice");
verify(userRepository, times(1)).findById(1L);
}
@Test
void findById_throwsException_whenUserNotFound() {
when(userRepository.findById(99L)).thenReturn(Optional.empty());
assertThatThrownBy(() -> userService.findById(99L))
.isInstanceOf(UserNotFoundException.class)
.hasMessageContaining("99");
}
}
Testing a Controller with @WebMvcTest
@WebMvcTest loads only the web layer — controllers, filters, and MVC config. No database or service beans load. Mock the service layer:
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired
private MockMvc mockMvc; ← Simulates HTTP requests
@MockBean
private UserService userService; ← Mock the service
@Test
void getUser_returns200_whenUserExists() throws Exception {
User user = new User(1L, "Alice", "alice@test.com");
when(userService.findById(1L)).thenReturn(user);
mockMvc.perform(get("/api/users/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("Alice"))
.andExpect(jsonPath("$.email").value("alice@test.com"));
}
@Test
void createUser_returns201_withValidBody() throws Exception {
String body = """
{"name": "Bob", "email": "bob@test.com", "age": 25}
""";
User saved = new User(2L, "Bob", "bob@test.com");
when(userService.create(any())).thenReturn(saved);
mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content(body))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.id").value(2));
}
}
Testing the Repository with @DataJpaTest
@DataJpaTest ← Uses H2 in-memory DB, loads only JPA layer
class UserRepositoryTest {
@Autowired
private UserRepository userRepository;
@Test
void findByEmail_returnsUser_whenEmailExists() {
User user = new User(null, "Alice", "alice@test.com");
userRepository.save(user);
Optional<User> result = userRepository.findByEmail("alice@test.com");
assertThat(result).isPresent();
assertThat(result.get().getName()).isEqualTo("Alice");
}
}
The Three A's of a Good Test
Arrange ← Set up test data and mocks
Act ← Call the method being tested
Assert ← Verify the result
@Test
void save_persistsUser() {
// Arrange
User user = new User(null, "Alice", "alice@test.com");
// Act
User saved = userService.save(user);
// Assert
assertThat(saved.getId()).isNotNull();
assertThat(saved.getName()).isEqualTo("Alice");
}
Common Assertions (AssertJ)
assertThat(result).isEqualTo(expected);
assertThat(list).hasSize(3);
assertThat(string).contains("hello");
assertThat(number).isGreaterThan(0);
assertThat(optional).isPresent();
assertThat(value).isNull();
assertThatThrownBy(() -> method()).isInstanceOf(SomeException.class);
Summary
spring-boot-starter-testincludes JUnit 5, Mockito, AssertJ, and MockMvc- Unit tests use
@Mockand@InjectMocksto test a class in isolation @WebMvcTesttests controller endpoints without loading the full app@DataJpaTesttests repository methods using an in-memory database- Structure every test with Arrange, Act, and Assert sections
