반응형
Notice
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
Tags
- 데이터분석
- 클라우드컴퓨팅
- 네트워크
- 빅데이터
- 보안
- 사이버보안
- 컴퓨터공학
- 인공지능
- 파이썬
- 소프트웨어공학
- 컴퓨터비전
- Yes
- 데이터구조
- 자바스크립트
- 소프트웨어
- 디자인패턴
- 알고리즘
- 프로그래밍언어
- springboot
- 웹개발
- 자료구조
- 프로그래밍
- 컴퓨터과학
- 딥러닝
- 머신러닝
- I'm Sorry
- 네트워크보안
- 데이터과학
- 버전관리
- 데이터베이스
Archives
- Today
- Total
스택큐힙리스트
자바 스프링 개발 시작하기 - 13일차 테스트 주도 개발 본문
반응형
1. TDD가 왜 중요한가?
“Red → Green → Refactor” 사이클을 통해 서비스 레이어의 요구사항을 코드로 먼저 검증하면, 새 기능을 추가해도 회귀 버그가 줄고 구조가 깔끔해집니다. 테스트가 있는 코드베이스는 리팩터링과 CI/CD에 강합니다.
2. JUnit 5 빠르게 세팅하기
Gradle 기준:
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.2'
testImplementation 'org.mockito:mockito-junit-jupiter:5.12.0'
testImplementation 'org.testcontainers:junit-jupiter:1.19.7'
}
test {
useJUnitPlatform()
}
Tip : 스프링 부트 3.x는 기본으로 JUnit 5 의존성을 포함하지만, 버전 충돌을 막기 위해 testImplementation에 명시하는 편이 안전합니다.
3. Mockito로 서비스 레이어 단위 테스트
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock private UserRepository userRepository;
@InjectMocks private UserService userService;
@Test
void createUser_success() {
UserSaveRequest req = new UserSaveRequest("jaemin", "jaemin@mail.com");
when(userRepository.save(any())).thenReturn(req.toEntity());
User result = userService.createUser(req);
assertAll(
() -> assertEquals("jaemin", result.getName()),
() -> verify(userRepository).save(any(User.class))
);
}
}
- Mock 객체로 외부 의존성을 격리 → 진짜 DB 없이도 로직 검증
- BDDMockito의 given-when-then 스타일을 쓰면 시나리오가 더 읽기 쉽습니다.
4. Testcontainers로 통합 테스트까지 확장
@Testcontainers
@SpringBootTest
class OrderServiceIntegrationTest {
@Container
static PostgreSQLContainer<?> postgres =
new PostgreSQLContainer<>("postgres:16-alpine")
.withDatabaseName("testdb");
@DynamicPropertySource
static void overrideProps(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
}
@Autowired OrderService orderService;
@Test
void placeOrder_success() {
// given
OrderRequest req = new OrderRequest(...);
// when
Order saved = orderService.placeOrder(req);
// then
assertThat(saved.getId()).isNotNull();
}
}
- 실제 컨테이너 기반 DB로 스프링 컨텍스트 전체를 검증
- 깃허브 Actions + services: 옵션으로 CI 상에서도 동일한 환경을 재현 가능
5. 유지 보수를 위한 실전 팁
- 테스트 네이밍 컨벤션: 메서드명_시나리오_기대결과
- Fixture 재사용: @TestConfiguration 또는 Fixture 클래스로 중복 제거
- 커버리지 목표: 단위 테스트 > 70 %, 통합 테스트 > 20 %부터 시작해 점진적 확대
- 테스트 실행 속도: 통합 테스트는 @Tag("integration")로 구분해 로컬/CI에서 선택적 실행
반응형
'개발' 카테고리의 다른 글
DD 패밀리 완전 정복 (1) | 2025.07.20 |
---|---|
TDD의 장점 (0) | 2025.07.20 |
Spring 캐시 추상화 × Flyweight 패턴: 메모리 폭주 0% 만드는 공식 (2) | 2025.07.19 |
Flyweight 패턴: 객체 수백만 개도 ‘가벼운’ 메모리로 돌리는 비결 (0) | 2025.07.19 |
인가와 인증 차이 (0) | 2025.07.19 |
Comments