본문 바로가기
오늘의 에러

@WebMvcTest와 WebMvcConfigurer을 같이 사용할 때 UnsatisfiedDependencyException 상황

by 데브겸 2024. 4. 17.

상황

예전에는 database의 사용을 Controller에서는 @Autowired로, 레포지터리에서는 @Repository로 의존성 주입을 하였음

하지만 계속 db 구현을 바꾸는 상황에서 한곳에서 변경을 관리하고자 WebMvcConfigurer를 구현한 WebConfig에서 빈 등록을 직접하고자 함

// Test Code

@WebMvcTest(controllers = ArticleController.class)
class ArticleControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private ArticleDatabase articleDatabase;
// WebConfig.java

@Configuration
public class WebConfig implements WebMvcConfigurer {
    private final DataSource dataSource;

    public WebConfig(DataSource dataSource){
        this.dataSource = dataSource;
    }

    @Bean
    public UserDatabase userDatabase() {
        return new H2UserDatabase(dataSource);
    }

    @Bean
    public ArticleDatabase articleDatabase() {
        return new H2ArticleDatabase(dataSource);
    }
}

 

그랬더니 @WebMvcTest로 구현한 테스트 코드가 안 돌아간다… (WebConfig 사용 전에 @Repository로 자동 주입할 때는 잘 되었음)

 

원인 분석

Error creating bean with name 'webConfig' defined in file

Caused by: Unsatisfied dependency expressed through constructor parameter 0: No qualifying bean of type 'javax.sql.DataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

Caused by: No qualifying bean of type 'javax.sql.DataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

 

에러를 잘 읽어보니 WebConfig에서 DataSource에 대한 의존성 주입이 없어서 에러가 난다는 것이었다. 

그런데 나는 테스트에서 @MockBean을 이용해서 테스트코드에서는 DataSource를 신경 안 쓰게 만들게 했는데 왠??

공식문서를 좀 뒤져보니 @WebMvcTest에서 WebMvcConfigurer 을 configuration 한다는 것이다.

 

Using this annotation will disable full auto-configuration and instead apply only configuration relevant to MVC tests(i.e. @Controller, @ControllerAdvice, @JsonComponent, Converter/GenericConverter, Filter, WebMvcConfigurer and HandlerMethodArgumentResolver beans but not @Component, @Service or @Repository beans)

공식문서 - WebMvcTest (Spring Boot 3.2.4 API)

 

스캔하면서 생성자에 있는 DataSource에 대한 의존성 주입이 없어 그 아래 빈들 등록에 실패하여 에러가 난 것 같았다.

 

즉 예전에는 WebConfig가 없어서 아예 @WebMvc가 스캔을 진행하더라도 DataSource의 의존성 주입 실패가 일어나지 않았으나, 이제는 그런 상황이 발생한 것.

 

해결

 

이를 해결하기 위해 @WebMvcTest를 진행할 때 WebConfig를 스캔의 대상에서 제외하는 방법을 사용하였다. 애초에 빈 등록 실패 상황을 막아버린 것.

 

@WebMvcTest(controllers = ArticleController.class,
        excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = WebConfig.class))
class ArticleControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private ArticleDatabase articleDatabase;

 

 

그랬더니 잘 됨 ㅋㅎㅋㅎ