TestConfiguration 사용하기, @Configuration 과 차이

DongHyun Kim·2023년 8월 29일
0

🚩이 글의 목표

@TestConfiguration 사용법을 익히고, @Configuration 과 차이에 대해 이해하고, 대신 사용하는 이유에 대한 설명


Test 에 사용할 클래스를 만들 때는 빈으로 주입 받거나, 객체로 직접 생성해야한다.

다음 방법들을 통해 어떻게 클래스의 인스턴스를 만들어서 사용할지 살펴보자

위와 같은 구조의 프로젝트일 때, Test 클래스에서 MemberFacade 를 생성하려면 MemberService 와 LogRepository 를 주입 받아야한다.

매 테스트마다 MemberFacade 객체 생성하기

딱 봐도 비효율 적이다! 이런 보일러 플레이트는 지양하자

MemberFacde 클래스에 @Component 를 붙여서 스프링 부트가 빈으로 생성하게 시키기

@RequiredArgsConstructor
@Slf4j
@Component // 빈으로 생성하도록 표시
public class MemberFacade {
    private final MemberService memberService;
    private final LogRepository logRepository;
		...
}
// Test Class
		...
    @Autowired
    MemberService memberService;
    @Autowired
    MemberRepository memberRepository;
    @Autowired
    LogRepository logRepository;
    @Autowired
    MemberFacade memberFacade;
		...

이 방법에 문제는 없지만,

단위 테스트를 위해선 외부에 의존성을 끊어야하기 때문에 좋은 방법이 아니다.

그리고 생성된 Bean의 재정의가 불가능하다. (@Configuration 과 @ComponenetScan 차이!)

또한 스프링 컨테이너가 너무 많은 빈을 관리하게 되면, 매번 빈을 호출할 때 더 많은 빈을 순회해야 되므로 성능상 안 좋을 것이라 예상된다.

@TestConfiguration 으로 테스트에서 빈 생성하도록 설정

// Test Class
@Slf4j
@SpringBootTest
public class MyTest{
		@Autowired
		MemberService memberService;
		@Autowired
		MemberRepository memberRepository;
		@Autowired
		LogRepository logRepository;
		@Autowired
		MemberFacade memberFacade;
		
		@TestConfiguration // 빈으로 생성하도록 설정 표시
		public static class Config{
		
		    @Bean
		    public static MemberFacade makeMemberFacade(MemberService memberService, LogRepository logRepository){
		        return new MemberFacade(memberService, logRepository);
		    };
		}
		...
}

위 방법은 Test 할 시에만 빈을 생성해서 관리하기 때문에 기존 애플리케이션 성능에도 지장없이 테스트할 수 있다.

또한 @TestConfiguration 을 이용한다면, 외부와 연결도 끊은 mock service 를 사용할 수 있다.

⚠️주의

@Configuration 을 static 내부 클래스로 빈 생성 시 MemberService, LogRepository 빈을 찾을 수 없다는 오류가 발생한다.

이는 @TestConfiguration 은 @TestComponent를 정의했기 때문에 Spring Boot 의 comonent scaning 에서 제외되기 때문이다.

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@TestComponent
public @interface TestConfiguration {
}

@Configuration 을 사용한다면 다음과 같이 외부로 클래스를 빼줘야한다

@Configuration
class Config{
    @Bean
    public MemberFacade makeMemberFacade(MemberService memberService, LogRepository logRepository){
        return new MemberFacade(memberService, logRepository);
    };
}

@Slf4j
@SpringBootTest
@Import(Config.class)
public class MyTest{

    @Autowired
    MemberService memberService;
    @Autowired
    MemberRepository memberRepository;
    @Autowired
    LogRepository logRepository;
    @Autowired
    MemberFacade memberFacade;
		...
}

참고: https://reflectoring.io/spring-boot-testconfiguration/

profile
do programming yourself

0개의 댓글