나는 내가 지금까지 테스트를 작성할 때 @SpringBootTest, @Transactional을 사용해서 해왔다.
이게 단지 서비스의 메서드를 검증하는 것이니 단위테스트라고 생각했는데 아니었다.
이렇게 실제로 의존성들을 껴서 테스트하는 것은 통합 테스트였다.
이 둘의 차이를 알아보자.
1. 단위 테스트 (Mocking을 사용하는 테스트)
- Mocking을 사용하면 외부 의존성(예: DB, 네트워크 요청)을 모킹함으로써 테스트 대상 클래스에 집중할 수 있습니다.
- DB에 의존하지 않고, 로직만 테스트하는 경우에 적합합니다.
- *
@Transactional
*이 필요하지 않습니다. Mock을 사용하여 의존성을 대체하기 때문에, 실제 DB 트랜잭션이 필요 없으며, 빠르게 테스트를 실행할 수 있습니다.
- 장점:
- 테스트 실행 속도가 빠릅니다.
- 외부 환경(데이터베이스, 외부 API)에 의존하지 않으므로 테스트가 안정적입니다.
- 특정 비즈니스 로직에 대한 테스트에 적합합니다.
2. 통합 테스트 (@Autowired
와 @Transactional
을 사용하는 테스트)
- 통합 테스트는 실제 Spring 컨텍스트에서 빈들을 주입받아, 애플리케이션이 실제로 어떻게 동작하는지 확인하는 테스트입니다.
- *
@Transactional
*을 사용하여 테스트가 끝난 후 DB 롤백을 함으로써, 실제 DB에 영향을 주지 않고 테스트할 수 있습니다.
- 실제 DB, 서비스, 리포지토리 등이 모두 연동된 상태에서 동작을 확인할 수 있습니다.
- 장점:
- 실제 환경과 비슷한 조건에서 테스트할 수 있으므로, 애플리케이션이 예상대로 동작하는지 전체적인 흐름을 검증할 수 있습니다.
- 여러 컴포넌트가 통합된 상태에서의 동작을 테스트하는데 유용합니다.
단위 테스트 vs 통합 테스트
구분 | 단위 테스트 (Mocking) | 통합 테스트 (@Transactional) |
테스트 속도 | 빠름 | 느림 |
의존성 | DB, 서비스 등의 의존성 없이 로직만 테스트 가능 | 실제 DB, 서비스 등을 모두 연동 |
테스트 범위 | 특정 클래스나 메서드에 집중 | 애플리케이션의 실제 흐름과 동작을 검증 |
외부 시스템 필요 여부 | 불필요 (Mock으로 대체) | 필요 (실제 DB, 서비스 등) |
목적 | 단일 컴포넌트의 비즈니스 로직을 테스트 | 애플리케이션의 전반적인 동작을 검증 |
3. 어떤 테스트가 더 나은가?
- 단위 테스트는 특정 클래스나 메서드의 동작을 정확하게 테스트하고, 외부 의존성 없이 빠르게 테스트할 수 있다는 점에서 매우 유용합니다.
- 하지만, 실제 환경에서의 통합적인 동작을 확인하려면 통합 테스트가 필요합니다. 통합 테스트는 애플리케이션의 흐름과 의존성이 모두 제대로 동작하는지 확인할 수 있기 때문에, 로직 전체의 안정성을 검증할 수 있습니다.
결론
- Mocking을 사용한 단위 테스트는 특정 로직에 대한 테스트 목적을 충분히 달성할 수 있습니다. 빠르고 독립적으로 동작하므로, 코드 변경 시 비즈니스 로직을 안전하게 확인할 수 있습니다.
- 그러나 통합 테스트는 실제 시스템과의 상호작용을 확인하고 전체적인 흐름을 테스트하는 데 유용합니다. 따라서 중요한 비즈니스 로직이나 애플리케이션의 핵심 흐름은 통합 테스트로 확인하는 것이 좋습니다.
두 가지 방식을 적절히 혼용하여 사용하는 것이 가장 이상적입니다. 핵심 로직에 대해서는 단위 테스트로, 전체 흐름과 의존성에 대해서는 통합 테스트로 검증하면 됩니다.