Spring/Spring err

[Spring Junit] @SpringBootTest + @Autowired 에러 "Could not autowire. No beans of "

민돌v 2023. 7. 5. 17:41
때는 바야흐로..

 

ATDD 과정 수강 중 각각의 E2E 인수테스트의 데이터베이스를 서로 영향받지않게 격리 시켜주기 위해
test 패키지에 만든 별도의 클래스를 빈으로 올려 @Autowired 로 주입받고자 했습니다. 

 

하지만 에러가 뜨는군요!

DataBaseCleanUp 이라는 Class는 Test 패키지 아래에서만 존재하는 클래스입니다.

@TestComponent
public class DataBaseCleanUp {
	.. 생략
}
  • @SpringBootConfiguration 의 scan 대상으로는 포함시키지 않기위해 @TestComponent 를 적용해 주었습니다.
  • @TestComponent는 Test 를 위한 Component 이지만, javadoc 설명처럼 직접적으로 ComponentScan 을 사용하는 경우 Filter 에 대한 정의를 해주어야하는 유의사항이 있습니다.

 

📌error code

java.lang.IllegalStateException: Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest(classes=...) with your test

 


@SpringBootTest 빈 컨텍스트 등록 과정

@SpringBootTest 어노테이션은 @SpringBootApplication이 있는 Application 을 찾아서 사용하고,

그렇게 찾은 @SpringBootApplication 안의 @ComponentScan이 스캔한 빈들을 그대로 스프링 컨텍스트에 올려서 사용한다고 하더군요

 

그리고 테스트에서 실행했기 때문에 test 중에서도 hello.core를 포함한 그 하위 패키지는 컴포넌트 스캔의 대상이 된다고 합니다,,,

 


에러 해결 방법 

📌 지금 깨달아서 해본건데 test 패키지 안에서도 '@SpringBootApplication이 있는 Application' 패키지 내부에 존재하는 컴포넌트들은 스캔의 대상이 됩니다..
따라서 패키지 구조를 잘 맞춰주면 됩니다. 

이렇게

 

📌 하지만 저 처럼 우매한 실수를 하거나 고집이 쎄서 맞추기 싫다! 하신다면 @ContextConfiguration 를 사용하시면 됩니다.

이런 구조였고 아래처럼, 컨택스트를 포함해줄 클래스에 추가해주었습니다.

@SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT)
@ContextConfiguration(classes= {DataBaseCleanUp.class, SubwayApplication.class})
public abstract class AcceptanceTestConfig {

    @Autowired
    DataBaseCleanUp dataBaseCleanUp;

    @BeforeEach
    void setUp() {
        dataBaseCleanUp.clean();
    }
}

 

 

 

결론.

테스트도 패키지 구조를 잘 맞추고

원리를 이해하고 코딩하자.. ㅠ