스프링 전환 테스트 참조 문서
1. 테스트 전략 개요
1.1 테스트 피라미드
▲
/E2E\ (End-to-End)
/──────\
/Integration\ (Integration)
/────────────\
/ Unit Tests \ (Unit)
/────────────────\
1.2 목표 커버리지
| 테스트 유형 |
목표 |
도구 |
| 단위 테스트 |
80% |
JUnit 5, Mockito |
| 통합 테스트 |
70% |
Spring Test, TestContainers |
| E2E 테스트 |
50% |
RestAssured |
2. 단위 테스트 기준
2.1 Service Layer 테스트
@SpringBootTest
class UserServiceTest {
@Autowired private UserService userService;
@MockBean private UserRepository userRepository;
@Test
void shouldCreateUserSuccessfully() {
// Given
UserDto dto = new UserDto("test@example.com", "password");
when(userRepository.save(any(User.class))).thenAnswer(i -> i.getArgument(0));
// When
User result = userService.createUser(dto);
// Then
assertThat(result.getEmail()).isEqualTo("test@example.com");
verify(userRepository).save(any(User.class));
}
@Test
void shouldThrowExceptionForDuplicateEmail() {
// Given
String email = "existing@example.com";
when(userRepository.findByEmail(email)).thenReturn(Optional.of(new User()));
// When/Then
assertThatThrownBy(() -> userService.createUser(new UserDto(email, "pass")))
.isInstanceOf(DuplicateEmailException.class);
}
}
2.2 Repository 테스트
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class UserRepositoryTest {
@Autowired private UserRepository userRepository;
@Autowired private TestEntityManager entityManager;
@Test
void shouldFindByEmail() {
// Given
User user = new User("test@example.com", "encoded");
entityManager.persist(user);
// When
Optional<User> found = userRepository.findByEmail("test@example.com");
// Then
assertThat(found).isPresent();
}
}
2.3 Controller 테스트
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired private MockMvc mockMvc;
@MockBean private UserService userService;
@Test
void shouldCreateUser() throws Exception {
// Given
CreateUserRequest request = new CreateUserRequest("test@example.com", "password");
when(userService.createUser(any())).thenReturn(new User(1L, "test@example.com"));
// When/Then
mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request)))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.email").value("test@example.com"));
}
}
3. 통합 테스트 기준
3.1 Database Integration Test
@SpringBootTest
@Testcontainers
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class UserRepositoryIntegrationTest {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15");
@DynamicPropertySource
static void properties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
}
@Test
void shouldPersistAndRetrieveUser() {
User user = new User("integration@test.com", "password");
User saved = userRepository.save(user);
Optional<User> found = userRepository.findById(saved.getId());
assertThat(found).isPresent();
}
}
4. 테스트 실행 기준
| 테스트 유형 |
실행 시점 |
실패 시 동작 |
| 단위 테스트 |
매 커밋 |
빌드 실패 |
| 통합 테스트 |
PR 생성 |
빌드 실패 |
| E2E 테스트 |
일 1회 |
알림 발송 |
| 성능 테스트 |
주 1회 |
보고 |
5. 검증 체크리스트
전환 완료 기준
코드 품질 기준