Spring Boot Testing: Unit, Integration & Performance

boot.cloud
Boot to Cloud
Published on May, 04 2026 3 min read 0 comments
image

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, and assertThrows

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.requests to see request times
  • Helps identify slow endpoints before production

Step 7: Best Practices for Testing

  1. Unit Tests: Isolate business logic
  2. Integration Tests: Test full flow with DB and controllers
  3. Use TestContainers for reproducible DB tests
  4. Mock external services to avoid network calls
  5. Test security and role-based access
  6. 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

0 Comments