🚀 Introduction: What is @SpringBootTest
in Spring Boot?
The @SpringBootTest
annotation in Spring Boot is used for integration testing by loading the full application context. It allows you to test Spring Boot components such as services, controllers, and repositories in a real Spring environment.
✅ Key Features of @SpringBootTest
:
✔ Loads the entire application context for testing.
✔ Supports dependency injection in test classes.
✔ Works with JUnit and TestNG for unit and integration tests.
✔ Can be configured to load specific components or mock dependencies.
📌 In this guide, you’ll learn:
✅ How @SpringBootTest
works in Spring Boot testing.
✅ How to configure @SpringBootTest
for different testing scenarios.
✅ Best practices for writing efficient tests.
1️⃣ Basic Example: Writing a Simple @SpringBootTest
📌 Example: Testing a Service Layer Using @SpringBootTest
1. Service Class (UserService.java
)
@Service
public class UserService {
public String getUserGreeting(String name) {
return "Hello, " + name + "!";
}
}
2. Test Class (UserServiceTest.java
)
@SpringBootTest
class UserServiceTest {
@Autowired
private UserService userService;
@Test
void testGetUserGreeting() {
String result = userService.getUserGreeting("Ramesh");
assertEquals("Hello, Ramesh!", result);
}
}
📌 Test Output (JUnit 5):
Test passed ✅
✅ The @SpringBootTest
annotation loads the application context and injects the UserService
bean.
2️⃣ @SpringBootTest
vs @WebMvcTest
vs @DataJpaTest
Annotation | Purpose | Components Loaded |
---|---|---|
@SpringBootTest |
Full application context testing | All Spring components (Controllers, Services, Repositories, Beans, etc.) |
@WebMvcTest |
Controller layer testing | Only controllers (@Controller or @RestController ) |
@DataJpaTest |
Repository and database layer testing | Only repository (@Repository ) beans with in-memory database |
📌 Example: Using @WebMvcTest
for Controller Testing
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
void testGetUser() throws Exception {
mockMvc.perform(get("/api/users/1"))
.andExpect(status().isOk())
.andExpect(content().string("User with ID: 1"));
}
}
✅ Use @WebMvcTest
for testing only the controller layer.
3️⃣ Using @SpringBootTest
with a Random Port (For API Testing)
Use @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
to start the application with a random port for real HTTP testing.
📌 Example: Testing REST API with Random Port
1. Controller (UserController.java
)
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/{id}")
public String getUserById(@PathVariable int id) {
return "User with ID: " + id;
}
}
2. Test Class (UserControllerTest.java
)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class UserControllerTest {
@Autowired
private TestRestTemplate restTemplate;
@Test
void testGetUserById() {
String response = restTemplate.getForObject("/api/users/1", String.class);
assertEquals("User with ID: 1", response);
}
}
📌 Test Output:
Test passed ✅
✅ The test runs with a random port and makes actual API calls using TestRestTemplate
.
4️⃣ Mocking Dependencies in @SpringBootTest
with @
MockitoBean
@MockBean
has been widely used to mock dependencies in test cases. However, starting from Spring Boot 3.2, @MockBean
is deprecated and replaced with @MockitoBean
.To avoid loading real database connections, use @MockitoBean
to create mock dependencies.
📌 Example: Mocking a Repository in @SpringBootTest
1. Repository (UserRepository.java
)
public interface UserRepository extends JpaRepository<User, Integer> {
Optional<User> findByEmail(String email);
}
2. Service (UserService.java
)
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public Optional<User> getUserByEmail(String email) {
return userRepository.findByEmail(email);
}
}
3. Test Class (UserServiceTest.java
)
@SpringBootTest
class UserServiceTest {
@Autowired
private UserService userService;
@MockitoBean
private UserRepository userRepository;
@Test
void testGetUserByEmail() {
when(userRepository.findByEmail("test@example.com"))
.thenReturn(Optional.of(new User(1, "Test User", "test@example.com")));
Optional<User> user = userService.getUserByEmail("test@example.com");
assertTrue(user.isPresent());
assertEquals("Test User", user.get().getName());
}
}
📌 Test Output:
Test passed ✅
✅ Using @
MockitoBean
, the repository is replaced with a mock object, avoiding actual database calls.
5️⃣ Testing a Spring Boot Application with CommandLineRunner
If your Spring Boot application uses a CommandLineRunner, disable it during testing to prevent unintended execution.
📌 Example: Disabling CommandLineRunner
in Tests
1. Command Line Runner (AppRunner.java
)
@Component
public class AppRunner implements CommandLineRunner {
@Override
public void run(String... args) {
System.out.println("Application started!");
}
}
2. Test Class with Disabled CommandLineRunner
@SpringBootTest(properties = "spring.main.allow-bean-definition-overriding=true")
class ApplicationTests {
@Test
void contextLoads() {
// No execution of CommandLineRunner
}
}
✅ Prevents CommandLineRunner
from running in tests.
🎯 Summary: Best Practices for Using @SpringBootTest
✅ Use @SpringBootTest
for full integration tests.
✅ Use @WebMvcTest
for testing only controllers.
✅ Use @
MockitoBean
to mock dependencies instead of real database connections.
✅ Use @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
for API tests.
✅ Disable CommandLineRunner
in test configurations when necessary.
🚀 Following these best practices ensures robust and maintainable tests in Spring Boot!
Comments
Post a Comment
Leave Comment