Spring Boot Testing: Unit Test และ Integration Test

#java13 เม.ย. 2569

Testing ใน Spring Boot

Spring Boot มี testing support ที่ดีมาก ด้วย @SpringBootTest, @WebMvcTest, @DataJpaTest และ Mockito

Unit Test กับ Mockito

import org.junit.jupiter.api.*;
import org.mockito.*;
import static org.mockito.Mockito.*;
import static org.assertj.core.api.Assertions.*;

@ExtendWith(MockitoExtension.class)
class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService;

    @Test
    void findById_WhenUserExists_ReturnsUser() {
        // Arrange
        User user = new User(1L, "สมชาย", "somchai@example.com");
        when(userRepository.findById(1L)).thenReturn(Optional.of(user));

        // Act
        Optional<User> result = userService.findById(1L);

        // Assert
        assertThat(result).isPresent();
        assertThat(result.get().getName()).isEqualTo("สมชาย");
        verify(userRepository, times(1)).findById(1L);
    }

    @Test
    void findById_WhenUserNotFound_ThrowsException() {
        when(userRepository.findById(99L)).thenReturn(Optional.empty());

        assertThatThrownBy(() -> userService.findById(99L))
            .isInstanceOf(UserNotFoundException.class)
            .hasMessageContaining("99");
    }
}

Controller Test กับ MockMvc

@WebMvcTest(UserController.class)
class UserControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private UserService userService;

    @Autowired
    private ObjectMapper objectMapper;

    @Test
    void getUser_WhenExists_Returns200() throws Exception {
        User user = new User(1L, "สมชาย", "somchai@example.com");
        when(userService.findById(1L)).thenReturn(Optional.of(user));

        mockMvc.perform(get("/api/users/1")
                .contentType(MediaType.APPLICATION_JSON))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.name").value("สมชาย"))
            .andExpect(jsonPath("$.email").value("somchai@example.com"));
    }

    @Test
    void createUser_WithValidData_Returns201() throws Exception {
        CreateUserRequest request = new CreateUserRequest("สมชาย", "somchai@example.com");
        User created = new User(1L, "สมชาย", "somchai@example.com");
        when(userService.create(any())).thenReturn(created);

        mockMvc.perform(post("/api/users")
                .contentType(MediaType.APPLICATION_JSON)
                .content(objectMapper.writeValueAsString(request)))
            .andExpect(status().isCreated())
            .andExpect(jsonPath("$.id").value(1));
    }
}

Repository Test

@DataJpaTest
class UserRepositoryTest {

    @Autowired
    private UserRepository userRepository;

    @Test
    void findByEmail_WhenExists_ReturnsUser() {
        User user = new User("สมชาย", "somchai@example.com");
        userRepository.save(user);

        Optional<User> found = userRepository.findByEmail("somchai@example.com");

        assertThat(found).isPresent();
        assertThat(found.get().getName()).isEqualTo("สมชาย");
    }
}

Integration Test

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureTestDatabase
class UserIntegrationTest {

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    void createAndGetUser() {
        CreateUserRequest request = new CreateUserRequest("สมชาย", "somchai@example.com");
        ResponseEntity<User> created = restTemplate.postForEntity("/api/users", request, User.class);

        assertThat(created.getStatusCode()).isEqualTo(HttpStatus.CREATED);
        Long id = created.getBody().getId();

        ResponseEntity<User> found = restTemplate.getForEntity("/api/users/" + id, User.class);
        assertThat(found.getStatusCode()).isEqualTo(HttpStatus.OK);
        assertThat(found.getBody().getName()).isEqualTo("สมชาย");
    }
}

สรุป

Spring Boot testing ครอบคลุมทุกระดับ ตั้งแต่ unit test ด้วย Mockito ไปจนถึง integration test ด้วย @SpringBootTest ควรเขียน test ทุกระดับเพื่อ confidence ที่สูงครับ