@SpringBootTest, 순수 스프링 컨테이너, @TestConfiguration 정리

2025. 8. 18. 14:48·Spring

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 속성 사용 전

classes 속성을 사용하기 전

  • 전체 애플리케이션의 모든 설정과 빈을 읽어들입니다
  • `ac.getBeanDefinitionCount()` 결과 : 458개

classes 속성 사용 후

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 추가 설명

주요 특징

  1. 운영 코드에서 제외: 컴포넌트 스캔 시 자동으로 제외
  2. @SpringBootTest에서 포함: 테스트 실행 시에는 자동 인식
  3. 싱글톤 관리 조건: 클래스 상단에 선언해야 의존관계까지 싱글톤 보장
  4. 테스트 전용 설정: 테스트에만 필요한 빈들을 명확히 분리

선언 위치에 따른 차이

상단 선언 (권장)

@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
'Spring' 카테고리의 다른 글
  • 스프링 트랜잭션 전파 속성별로 실습 해보기
  • Spring Cloud Gateway와 WebFlux 관계 이해하기 (2편)
  • Spring Cloud Gateway와 WebFlux 관계 이해하기 (1편)
  • Spring Cloud Gateway에서 라우팅 설정 방법
꾸준히 기록하는 지수
꾸준히 기록하는 지수
서비스 백엔드 개발자가 되기 위해 제 경험들을 하나씩 기록해봅니다
  • 꾸준히 기록하는 지수
    지수블로그
    꾸준히 기록하는 지수
  • 전체
    오늘
    어제
    • 분류 전체보기 (37)
      • Spring (15)
      • JAVA (9)
      • 클라우드_인프라 (4)
      • Data (5)
      • CS (3)
      • 돌아보기 (0)
      • 취업준비 (1)
  • 블로그 메뉴

    • 홈
    • 태그
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    데이터아키텍처준전문가
    트랜잭션전파
    DAsP
    SpringCloudGateway
    DASP합격
    DASP후기
    Spring
    스프링테스트
    AWS
    궁금증
    DASP합격후기
    트랜잭션
    MSA
    SCG
    자격증
    스프링트랜잭션
    스프링클라우드
    스프링부트
    트러블슈팅
    스프링
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
꾸준히 기록하는 지수
@SpringBootTest, 순수 스프링 컨테이너, @TestConfiguration 정리
상단으로

티스토리툴바