In Week 6, we implemented professional error handling and logging.
Now, in Week 7, we’ll focus on testing your Spring Boot application — a critical skill for production-ready APIs.
We’ll cover:
- Unit testing for isolated logic
- Integration testing for controllers, services, and repositories
- Performance testing basics
- Using JUnit 5, Mockito, and Spring Test
Why Testing Matters
❌ Without tests:
- Bugs sneak into production
- Refactoring is risky
- Deployment confidence is low
✅ With tests:
- You catch errors early
- Code is maintainable and refactor-friendly
- Continuous integration works reliably
Remember: Tests are documentation + safety net.
Step 1: Add Testing Dependencies
In pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>1.19.0</version>
<scope>test</scope>
</dependency>spring-boot-starter-test→ JUnit 5, AssertJ, Spring Test utilities- Mockito → Mock dependencies in unit tests
- TestContainers → Integration testing with real databases
Step 2: Unit Testing Service Layer
Example: UserServiceTest
@ExtendWith(MockitoExtension.class)
public class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
@Test
void testSaveUser() {
User user = new User();
user.setName("Mahabub");
user.setEmail("[email protected]");
when(userRepository.save(any(User.class))).thenReturn(user);
User saved = userService.saveUser(user);
assertNotNull(saved);
assertEquals("Mahabub", saved.getName());
verify(userRepository, times(1)).save(user);
}
}✅ Key points:
- Mock repository to isolate service logic
- Verify interactions with
verify() - Use
assertEquals,assertNotNull, andassertThrows
Step 3: Integration Testing Controller Layer
Example: UserControllerTest
@SpringBootTest
@AutoConfigureMockMvc
public class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@Test
void testGetUserById() throws Exception {
User user = new User();
user.setId(1L);
user.setName("Mahabub");
when(userService.getUserById(1L)).thenReturn(Optional.of(user));
mockMvc.perform(get("/api/users/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("Mahabub"));
}
}✅ Key points:
@SpringBootTest→ Loads full Spring context@AutoConfigureMockMvc→ Mock HTTP requests@MockBean→ Replace service with mock
Step 4: Integration Testing with Database
Use TestContainers to spin up a real database during tests:
@Testcontainers
@SpringBootTest
public class UserRepositoryTest {
@Container
public static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15")
.withDatabaseName("testdb")
.withUsername("user")
.withPassword("pass");
@Autowired
private UserRepository userRepository;
@Test
void testSaveAndFindUser() {
User user = new User();
user.setName("Mahabub");
user.setEmail("[email protected]");
userRepository.save(user);
Optional<User> found = userRepository.findById(user.getId());
assertTrue(found.isPresent());
assertEquals("Mahabub", found.get().getName());
}
}✅ Benefits:
- Tests run against real database
- No need for manual setup/teardown
- Supports CI/CD pipelines
Step 5: Testing Security (JWT Protected Endpoints)
@Test
void testProtectedEndpoint() throws Exception {
mockMvc.perform(get("/api/admin")
.header("Authorization", "Bearer " + jwtToken))
.andExpect(status().isOk());
}- Generate JWT during test or mock authentication
- Ensure role-based access works as expected
Step 6: Performance Testing Basics
For simple API performance checks:
- Use Spring Boot Actuator / Metrics
- Use JMeter / Gatling / k6 for load testing
Example using Actuator metrics:
management:
endpoints:
web:
exposure:
include: health, metrics, httptrace- Access
/actuator/metrics/http.server.requeststo see request times - Helps identify slow endpoints before production
Step 7: Best Practices for Testing
- Unit Tests: Isolate business logic
- Integration Tests: Test full flow with DB and controllers
- Use TestContainers for reproducible DB tests
- Mock external services to avoid network calls
- Test security and role-based access
- Measure performance for heavy endpoints
Tip: Aim for >80% coverage in critical modules
Week 7 Recap
✅ Unit testing with Mockito
✅ Controller & service integration tests
✅ TestContainers for database
✅ JWT-protected endpoint tests
✅ Performance monitoring basics
✅ Best practices for maintainable test suites
What’s Next? (Week 8)
👉 Spring Boot Production Deployment & Optimization
We’ll cover:
- Profiles and environment variables
- Packaging and Dockerization
- Cloud deployment (AWS / Azure / GCP)
- Performance tuning and monitoring
📌 Action Items
✔ Write unit tests for all services
✔ Write integration tests for controllers
✔ Test endpoints with JWT authentication
✔ Add TestContainers for database
✔ Measure response times with Actuator