테스트 코드는 내가 작성한 코드가 의도한 대로 정확하게 동작하는지를 검증하는 코드로, 소프트웨어의 안정성을 보장하고, 리팩토링 시 자신감을 주며, 코드 자체를 설명하는 살아있는 문서의 역할을 합니다.
테스트 피라미드: 안정적이고 효율적인 테스트 전략을 수립하기 위한 모델입니다.
전략: 빠르고 안정적인 단위 테스트를 가장 많이 작성하고, 꼭 필요한 부분에만 통합 테스트를 추가하여 효율적인 테스트 스위트를 구성해야 합니다.
@ExtendWith(MockitoExtension.class): Spring 컨테이너의 도움 없이, 순수 JUnit과 Mockito만으로 테스트를 실행하여 매우 가볍고 빠릅니다.@Mock: 가짜(Mock) 객체를 생성합니다. (e.g., PostRepository)@InjectMocks: 테스트 대상이 되는 객체를 생성하고, @Mock으로 생성된 가짜 객체들을 자동으로 주입해줍니다. (e.g., PostService)given(...).willReturn(...): Mock 객체의 특정 메서드가 호출될 때, 어떤 값을 반환할지를 정의(Stubbing)합니다.@ExtendWith(MockitoExtension.class)
class PostServiceTest {
@Mock
private PostRepository postRepository;
@InjectMocks
private PostService postService;
@Test
@DisplayName("게시글 단건 조회 성공")
void findPostById_Success() {
// given - 테스트 준비
Long postId = 1L;
Post mockPost = new Post("테스트 제목", "테스트 내용");
// postRepository.findById(1L)가 호출되면, mockPost를 담은 Optional을 반환하도록 정의
given(postRepository.findById(postId)).willReturn(Optional.of(mockPost));
// when - 테스트 실행
PostResponse response = postService.findPostById(postId);
// then - 결과 검증
assertThat(response.getTitle()).isEqualTo("테스트 제목");
assertThat(response.getContent()).isEqualTo("테스트 내용");
// postRepository의 findById 메서드가 정확히 1번 호출되었는지 검증
verify(postRepository, times(1)).findById(postId);
}
}
@WebMvcTest: 웹 계층만(@Controller 등)을 테스트하기 위한 슬라이스 테스트 어노테이션입니다. @Service, @Repository 등은 로드하지 않으므로, 이들은 @MockBean으로 대체해야 합니다.MockMvc: 실제 서버를 띄우지 않고도, HTTP 요청을 시뮬레이션하고 응답 결과를 검증할 수 있게 해주는 강력한 테스트 도구입니다.@WebMvcTest(PostController.class) // PostController와 관련된 웹 계층만 테스트
class PostControllerTest {
@Autowired
private MockMvc mockMvc; // HTTP 요청 시뮬레이터
@MockBean // PostController가 의존하는 PostService를 가짜 Bean으로 등록
private PostService postService;
@Test
@DisplayName("게시글 단건 조회 API 성공")
void getPost_Success() throws Exception {
// given
Long postId = 1L;
PostResponse mockResponse = new PostResponse(postId, "제목", "내용", LocalDateTime.now());
// postService.findPostById(1L)가 호출되면, mockResponse를 반환하도록 정의
given(postService.findPostById(postId)).willReturn(mockResponse);
// when & then
mockMvc.perform(get("/api/posts/{id}", postId) // GET /api/posts/1 요청
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk()) // HTTP 상태 코드가 200 OK인지 확인
.andExpect(jsonPath("$.title").value("제목")) // 응답 JSON의 title 필드 값 확인
.andDo(print()); // 요청/응답 내용 상세 출력
}
}
@ExtendWith(MockitoExtension.class))에 적합합니다.@WebMvcTest와 MockMvc를 사용하여 웹 계층만 가볍고 빠르게 테스트할 수 있습니다.