6단계
6단계 — 테스트 전략
25 분
6단계 — 테스트 전략
테스트는 나중에 가 아니라 지금 입니다. 코드를 짜면서 테스트도 짜면 회귀 (퇴행) 가 0 가까워져요.
세 가지 층
| 층 | 도구 | 무엇을 검증 |
|---|---|---|
| 단위 (unit) | JUnit 5 + Mockito | 한 클래스의 한 메서드 |
| 통합 (integration) | @SpringBootTest + Testcontainers |
여러 빈 + 실제 DB |
| E2E | RestAssured / Playwright | HTTP 요청 → 응답 |
신규 코드는 단위 + 통합 둘 다 권장. E2E 는 핵심 흐름만.
통합 테스트 — Testcontainers 가 답
@SpringBootTest
@Testcontainers
class PostControllerTest {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:17");
@DynamicPropertySource
static void config(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
}
@Autowired MockMvc mockMvc;
@Test
void 게시물_생성_API_는_201_을_반환한다() throws Exception {
mockMvc.perform(post("/api/posts")
.contentType("application/json")
.content("""
{"title":"제목","body":"본문"}
"""))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.id").exists());
}
}
Docker 가 자동으로 PostgreSQL 컨테이너를 띄워요. mock DB 보다 실제 DB 가 진짜 회귀 를 더 잘 잡습니다.
단위 테스트 — Mockito
@ExtendWith(MockitoExtension.class)
class PostServiceTest {
@Mock PostRepository repository;
@InjectMocks PostService service;
@Test
void 존재하지_않는_ID_조회는_NotFoundException_을_던진다() {
when(repository.findById(999L)).thenReturn(Optional.empty());
assertThatThrownBy(() -> service.findById(999L))
.isInstanceOf(NotFoundException.class);
}
}
한국어 메서드 이름
@Test 메서드 이름은 한국어로 조건 → 결과 를 풀어쓰면 실패 원인이 한눈에 보여요.
직접 해 보기
PostController 에 @DeleteMapping("/{id}") 통합 테스트를 추가해 보세요. (1) 게시물을 만들고 (2) 삭제 API 를 호출해 (3) 204 No Content 응답이 오는지 + (4) 다시 GET 시 404 가 오는지.
더 깊이
다음 단계
마지막 7단계에서는 이 모든 코드를 사용자에게 보여줄 배포 를 한 번에 끝내요.