SpringBoot에서 테스트코드를 작성하면서 경험한 오류들로 이 포스팅을 작성하게 되었습니다
`@SpringBootTest` vs 순수 스프링 컨테이너의 비교와 `@TestConfiguration`에 대해 추가 설명을 작성했습니다
✅ @SpringBootTest - 통합 테스트의 완전체
주요 특징
- 전체 애플리케이션 컨텍스트 로드: 실제 운영 환경과 동일한 조건으로 모든 빈을 로드
- 모든 설정 클래스 스캔: @Configuration, @Component 등 모든 설정을 자동으로 읽음
- application.properties 자동 로드: 운영 설정 파일을 그대로 사용
- AutoConfiguration 자동 적용: Spring Boot의 자동 설정 기능 활용
🚩 '전체', '모든' 키워드에 집중해야 합니다. 운영코드, 테스트코드에 있는 모든 빈을 스프링 컨테이너로 등록하고 관리합니다.
‼️ @SpringBootTest를 쓰는데 스프링 빈 범위를 제한하고 싶은 경우
@SpringBootTest는 기본적으로 모든 빈을 등록하지만, `classes` 속성을 사용하면 특정 클래스의 빈만 등록할 수 있습니다.
@ComponentScan(
basePackages = {"com.jisutudy.service"}
)
public class ZsuTestConfig {
@Bean
public JpaSmsRepository jpaSmsRepository() {
return Mockito.mock(JpaSmsRepository.class);
}
@Bean
public JpaSmsTemplateRepository jpaSmsTemplateRepository() {
return Mockito.mock(JpaSmsTemplateRepository.class);
}
@Bean
public JpaTemplateVariableRepository jpaTemplateVariableRepository() {
return Mockito.mock(JpaTemplateVariableRepository.class);
}
@Bean
public SmsQueryDsl smsQueryDsl() {
return Mockito.mock(SmsQueryDsl.class);
}
@Bean
public CustApiService custApiService() {
return Mockito.mock(CustApiService.class);
}
@Bean
public ItemApiService itemApiService() {
return Mockito.mock(ItemApiService.class);
}
}
위와 같이 설정 클래스를 작성하여 컴포넌트 스캔으로 @SpringBootTest로 로드할 스프링 빈의 범위를 제한을 했습니다.
basePackages에서 지정한 패키지의 의존관계가 있는 스프링빈들은 Mock으로 직접 수동등록하여 테스트 환경을 구성했습니다.
실제 빈 개수 비교 결과

classes 속성을 사용하기 전
- 전체 애플리케이션의 모든 설정과 빈을 읽어들입니다
- `ac.getBeanDefinitionCount()` 결과 : 458개

classes 속성을 사용 후
- ZsuTestConfig.class를 classes 속성에 지정했습니다
- `ac.getBeanDefinitionCount()` 결과 : 27개 (458->27로 대폭 감소!)
⚠️ @SpringBootTest의 주의사항과 해결책
- 문제: 동일한 타입의 빈이 여러 개 등록되면 `NoUniqueBeanDefinitionException` 발생
- 아래 예시를 보면 파란색 동그라미 친 부분을 보면 예외가 발생하는 것을 확인할 수 있습니다

- 해결: @TestConfiguration 클래스를 생성하여 테스트용 빈을 수동 등록

TimeSmsFilter가 중복으로 발견되는 `NoUniqueBeanDefinitionException` 이 발생했을때, @TestConfiguration 클래스에 TimeSmsFilter 스프링 빈을 수동으로 등록하여 테스트를 통과할 수 있습니다.
🛠️ @Import를 활용한 테스트 설정
@Import(ClassName.class)를 사용하면 특정 설정 클래스를 테스트 어플리케이션 컨텍스트에 추가할 수 있습니다.
@SpringBootTest
@Import(TestConfig.class)
class MyTest {
// TestConfig의 빈들이 기존 애플리케이션 빈과 병합됨
}
@TestConfiguration
class TestConfig {
@Bean
public MockService mockService() {
return new MockService();
}
}
@Import vs classes 속성 비교
- @Import : 기존 애플리케이션 빈에 추가 및 병합 (추가 및 덮어씌우기와 같은 역할)
- classes 속성 : 지정된 클래스를 애플리케이션의 시작점으로 간주 (해당 클래스 기준으로만 로드)
✅ 순수 스프링 컨테이너 테스트
`AnnotationConfigApplicationContext`를 직접 사용하는 방법입니다.
주요 특징
- 필요한 설정만 로드: 지정한 `@Configuration` 클래스만 사용
- 빠른 테스트 실행: 전체 애플리케이션을 로드하지 않아 속도가 빠름
- 격리된 환경: 다른 빈들과의 간섭 없이 특정 기능만 테스트
- 제한사항:
- application.properties 자동 로드 안됨
- AutoConfiguration 적용 안됨 (JPA, 웹 MVC등의 자동 설정 관련 빈들이 자동생성 불가)
@Test
public void testWithPureSpring() throws Exception {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
ac.getEnvironment().setActiveProfiles("dev","prod");
ac.register(ZsuTestConfig.class);
ac.refresh();
System.out.println("ac.getBeanDefinitionCount() = " + ac.getBeanDefinitionCount());
for (String name : ac.getBeanDefinitionNames()) {
System.out.println("name = " + name);
}
}
✅ @TestConfiguration 추가 설명
주요 특징
- 운영 코드에서 제외: 컴포넌트 스캔 시 자동으로 제외
- @SpringBootTest에서 포함: 테스트 실행 시에는 자동 인식
- 싱글톤 관리 조건: 클래스 상단에 선언해야 의존관계까지 싱글톤 보장
- 테스트 전용 설정: 테스트에만 필요한 빈들을 명확히 분리
선언 위치에 따른 차이
상단 선언 (권장)
@SpringBootTest
class MyTest {
@TestConfiguration // 상단 선언
static class TestConfig {
@Bean
public ServiceA serviceA() {
return new ServiceA();
}
@Bean
public ServiceB serviceB(ServiceA serviceA) {
return new ServiceB(serviceA); // 의존관계도 싱글톤
}
}
}
상단 미선언
@SpringBootTest
class MyTest {
static class TestConfig { // @TestConfiguration 없음
@Bean
public ServiceA serviceA() {
return new ServiceA(); // 빈만 싱글톤
}
@Bean
public ServiceB serviceB(ServiceA serviceA) {
return new ServiceB(serviceA); // 의존관계는 매번 새 인스턴스
}
}
}
Static Inner Class 사용 팁
의존관계가 복잡하지 않은 단순한 빈들의 경우, @TestConfiguration 없이도 사용할 수 있습니다.
@SpringBootTest
class SimpleTest {
static class SimpleConfig { // 의존관계 없음
@Bean
public MockService mockService() {
return new MockService(); // 단순 빈만 생성
}
}
}
📊 테스트 전략별 선택 가이드
| 테스트 유형 | 추천 방법 | 장점 | 단점 |
| 통합 테스트 | @SpringBootTest | 실제 환경과 동일, 전체 기능 검증 | 느린 속도, 복잡한 설정 |
| 단위 테스트 | 순수 스프링 컨테이너 | 빠른 속도, 격리된 환경 | 제한적 기능, 수동 설정 필요 |
| 특정 레이어 테스트 | @TestConfiguration + @Import | 필요한 부분만 테스트, 유연한 설정 | 중간 수준의 복잡성 |
🎉 마무리
Spring Boot 테스트는 상황에 맞는 적절한 설정 선택이 핵심입니다.
- 통합 테스트가 필요하면 @SpringBootTest를
- 빠른 단위 테스트가 필요하면 순수 스프링 컨테이너를
- 그리고 특별한 테스트 설정이 필요하면 @TestConfiguration을 활용하세요.
각 방법의 특성을 이해하고 프로젝트의 요구사항에 맞게 조합하면 효과적인 테스트 코드를 작성할 수 있습니다.
'Spring' 카테고리의 다른 글
| 스프링 트랜잭션 전파 속성별로 실습 해보기 (0) | 2026.02.01 |
|---|---|
| Spring Cloud Gateway와 WebFlux 관계 이해하기 (2편) (1) | 2025.06.29 |
| Spring Cloud Gateway와 WebFlux 관계 이해하기 (1편) (0) | 2025.05.06 |
| Spring Cloud Gateway에서 라우팅 설정 방법 (0) | 2025.03.17 |
| Spring Cloud Gateway 동적 라우팅 추가시 Lambda 표현식 (0) | 2025.03.13 |
