JUnit 테스트에서 카프카 의존성 제외하기

dasd412·2022년 12월 10일
0

MSA 프로젝트

목록 보기
9/25

문제 상황

카프카 의존성을 추가하고 나서 JUnit 테스트가 작동하지 않았다. Brokers may not be available과 같은 에러 메시지를 계속 뱉으면서 무한루프를 돌고 있었다.

기존 코드

카프카 리스너

@EnableBinding(Sink.class)
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
    
    @StreamListener(Sink.INPUT)
    public void logSinkMessage(DiaryChangeModel diaryChange) {
			...
    }
}

@SpringBootApplication을 부착한 클래스에 카프카 어노테이션을 부착한 상태이다.

서비스 레이어

@Service
public class Serivce {
	private final Repository repo;
    private final KafkaSourceBean kafka;
    ...
}

서비스에는 특정 카프카 처리를 위한 빈이 주입된다.

카프카 처리 빈

@Component
public class KafkaSourceBean {
    private final Source source;
    ...
}

@Component이기 때문에 @SpringBootTest 기동 시, 컴포넌트 스캔에 의해 자동 생성된다.

테스트 코드

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@TestPropertySource(locations = "/application-test.properties")
@DirtiesContext(classMode = BEFORE_EACH_TEST_METHOD)
public class SaveTest {
	...
}

문제 원인 파악

@SpringBootTest(classes = Application.class)이기 때문에 Application.class를 기준으로 하위 패키지들이 전부 컴포넌트 스캔된다. 그에 따라 테스트 환경에 필요 없는 카프카 빈들도 자동 주입되고 말았다.

그래서 테스트 환경 (또는 프로파일)일 경우에는 카프카 의존성을 주입하지 않도록 조정할 필요가 있겠다.

해결책

  1. @EnableAutoConfiguration(exclude = {KafkaAutoConfiguration.class}) 를 테스트 클래스에 부착한다.
  2. 1.이 안되면 다음 해결책을 따라해보자.

1. 카프카 전용 설정 클래스 만들기

카프카 빈에서 @Component 제외

public class KafkaSourceBean {
    private final Source source;
}

설정 클래스에서 카프카 빈 직접 생성하기

@EnableBinding(Source.class)
@ConditionalOnProperty(value = "kafka.enabled", matchIfMissing = true)
@Configuration
public class KafkaConfiguration {

    @Autowired
    private Source source;

    @Bean
    public KafkaSourceBean kafkaSourceBean() {
        return new KafkaSourceBean(source);
    }
}

여기서 중요한 것은 @ConditionalOnProperty(value = "kafka.enabled", matchIfMissing = true)이다.

properties나 yml 파일에 kafka.enabled가 true여야만 위 설정 클래스가 빈으로 로딩된다.

즉, 테스트용 properties에는 false로 작성하면 빈으로 등록되지 않을 것이다.

2. 테스트용 프로퍼티에 설정 넣기

kafka.enabled=false

참고로, "false"가 아니라 false다.

3. 테스트에 @MockBean 넣기

@RunWith(SpringRunner.class)
@SpringBootTest(classes = DiaryServiceApplication.class)
@TestPropertySource(locations = "/application-test.properties")
public class SaveDiaryControllerTest {

	@Autowired
    private Service service;
    
    @MockBean
    private KafkaSourceBean kafka;
}

먼저, @TestPropertySource(locations = "/application-test.properties")를 이용해서 테스트 시에만 사용되는 properties를 지정하자.
아니면 Spring Profile 기능을 활용하여 분리해도 된다.

그리고 @MockBean으로 서비스에서 빠져버린 카프카 의존성을 가짜로 대체해주자.

참고 링크

https://velog.io/@roycewon/Component-Scan%EC%97%90-%EA%B4%80%ED%95%98%EC%97%AC

https://velog.io/@leejisoo/SpringBootTest-%EC%A0%95%EB%A6%AC

https://oingdaddy.tistory.com/476

https://stackoverflow.com/questions/58448677/how-to-disable-enablekafka-in-spring-boot-tests

https://stackoverflow.com/questions/54426658/control-enabling-disabling-kafka-consumers-in-spring-boot?rq=1

profile
아키텍쳐 설계와 테스트 코드에 관심이 많음.

0개의 댓글