Let's start from the very beginning. Why even bother with testing? You don't want your users running into bugs in production, right? Testing helps you find and fix problems before they hurt your app or your reputation. And Spring Boot gives you handy tools to make that easier.
Spring Boot integrates with popular testing libraries like JUnit and TestNG, and adds extra features via spring-boot-starter-test. That starter includes everything you need to write tests:
- JUnit 5 for writing tests.
- AssertJ for concise assertions.
- Hamcrest for expressive matchers.
- Mockito for creating stubs (mock objects).
- Spring Test — the Spring module that helps test apps inside the Spring context.
Setting up the test environment
First, make sure your pom.xml or build.gradle has a dependency on spring-boot-starter-test.
<!-- pom.xml -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
Spring Boot Test basics
With spring-boot-starter-test you get a powerful setup for testing Spring components: controllers, services, repositories, and even the whole system end-to-end.
Spring Boot Test annotations
@SpringBootTest— boots up the full application context for integration tests.@MockBean— creates test (mock) versions of beans. Handy for isolating the logic under test.@WebMvcTest— brings up only the Spring MVC context, great for testing REST controllers.@DataJpaTest— creates a context for testing repositories and JPA-related stuff.
Example: suppose we have a method in a service that returns a list of users. Using these annotations we can test its logic.
// UserService.java
@Service
public class UserService {
public List<String> getUsers() {
return Arrays.asList("Alice", "Bob", "Charlie");
}
}
// UserServiceTest.java
@SpringBootTest
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
public void testGetUsers() {
List<String> users = userService.getUsers();
assertEquals(3, users.size());
assertTrue(users.contains("Alice"));
}
}
Testing practice
Now let's look at how to test different parts of our app.
Testing REST controllers
Typical controller:
// UserController.java
@RestController
@RequestMapping("/users")
public class UserController {
@GetMapping
public List<String> getUsers() {
return List.of("Alice", "Bob", "Charlie");
}
}
Testing with @WebMvcTest:
@WebMvcTest(UserController.class)
public class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testGetUsers() throws Exception {
mockMvc.perform(get("/users"))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0]").value("Alice"))
.andExpect(jsonPath("$[1]").value("Bob"));
}
}
What's going on here?
- We use
MockMvcto perform HTTP requests against our controller. - The
perform()method sends a GET request to/users. - With
andExpect()we check the response status and the JSON array contents.
Testing repositories
Let's look at an example with JPA. We write a repository to manage the User entity.
Entity:
// User.java
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// getters & setters
}
Repository:
// UserRepository.java
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByName(String name);
}
Repository test:
@DataJpaTest
public class UserRepositoryTest {
@Autowired
private UserRepository userRepository;
@Test
public void testFindByName() {
// Arrange
User user = new User();
user.setName("Alice");
userRepository.save(user);
// Act
List<User> users = userRepository.findByName("Alice");
// Assert
assertEquals(1, users.size());
assertEquals("Alice", users.get(0).getName());
}
}
Notes:
- We use
@DataJpaTestto auto-configure an in-memory database (for example, H2). - In the Arrange step we add test data to the repository.
- The Act step runs the method under test.
- The Assert step verifies the results.
Integration testing
Sometimes you want to test the whole app, covering all layers — from controllers to the database. For that we use @SpringBootTest.
Example:
@SpringBootTest
public class IntegrationTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testGetUsers() throws Exception {
mockMvc.perform(get("/users"))
.andExpect(status().isOk())
.andExpect(content().string("[\"Alice\",\"Bob\",\"Charlie\"]"));
}
}
Important points
1. Using H2 for tests.
Spring Boot will auto-attach the H2 Database in tests if you're using JPA. That lets you test database stuff without spinning up a real DB server.
2. Using mock objects with Mockito.
Mockito lets you mock dependencies to isolate the code under test. For example:
@MockBean
private UserService userService;
@Test
public void testMockedService() {
when(userService.getUsers()).thenReturn(List.of("MockedUser"));
// Your test code here
}
Benefits of testing with Spring Boot
- Convenient integration. All the tools work together, so you don't have to wire everything manually.
- Efficiency. Tests run fast, even with an in-memory database.
- Reliability. Good test coverage helps avoid nasty surprises in production.
Now you're equipped with the core knowledge you need to test Spring Boot apps. Remember: any change in code deserves a test. Test everything that moves (and even what doesn't yet). And, as they say, "better a small test than a big apology to the client".
GO TO FULL VERSION