javaadvanced

Spring Boot Integration Testing

Write Spring Boot integration tests with MockMvc, test slices, TestContainers, and mock beans.

java
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;

import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

import java.util.List;
import java.util.Optional;

@SpringBootTest
@AutoConfigureMockMvc
class UserControllerIntegrationTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private UserService userService;

    @Test
    void shouldReturnUserById() throws Exception {
        when(userService.findById(1L))
            .thenReturn(Optional.of(new User(1L, "Alice", "alice@test.com")));

        mockMvc.perform(get("/api/users/{id}", 1))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.name").value("Alice"))
            .andExpect(jsonPath("$.email").value("alice@test.com"));
    }

    @Test
    void shouldReturn404WhenUserNotFound() throws Exception {
        when(userService.findById(99L)).thenReturn(Optional.empty());

        mockMvc.perform(get("/api/users/{id}", 99))
            .andExpect(status().isNotFound());
    }

    @Test
    void shouldCreateUser() throws Exception {
        String json = "{\"name\": \"Bob\", \"email\": \"bob@test.com\"}";
        when(userService.create(any())).thenReturn(new User(2L, "Bob", "bob@test.com"));

        mockMvc.perform(post("/api/users")
                .contentType(MediaType.APPLICATION_JSON)
                .content(json))
            .andExpect(status().isCreated())
            .andExpect(jsonPath("$.id").value(2))
            .andExpect(jsonPath("$.name").value("Bob"));

        verify(userService).create(any());
    }

    @Test
    void shouldReturnAllUsers() throws Exception {
        when(userService.findAll()).thenReturn(List.of(
            new User(1L, "Alice", "alice@test.com"),
            new User(2L, "Bob", "bob@test.com")
        ));

        mockMvc.perform(get("/api/users"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.length()").value(2))
            .andExpect(jsonPath("$[0].name").value("Alice"));
    }

    @Test
    void shouldValidateInput() throws Exception {
        String invalid = "{\"name\": \"\", \"email\": \"not-an-email\"}";

        mockMvc.perform(post("/api/users")
                .contentType(MediaType.APPLICATION_JSON)
                .content(invalid))
            .andExpect(status().isBadRequest());
    }
}

// Placeholder types
record User(Long id, String name, String email) {}
interface UserService {
    Optional<User> findById(Long id);
    List<User> findAll();
    User create(Object dto);
}

Use Cases

  • REST API endpoint verification
  • Controller and service layer testing
  • Input validation and error response testing

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.