일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- 의존성
- 우아한세미나
- MSA
- AWS
- 우테코
- HTTP
- 코드리뷰
- CircuitBreaker
- Spring Batch
- 우아한테크코스
- 스프링 부트
- 트랜잭션
- 미션
- mock
- Paging
- 세션
- JPA
- 자바
- 프리코스
- yml
- JUnit5
- Level2
- Docker
- AOP
- 레벨2
- 백준
- 프로그래머스
- REDIS
- 스프링부트
- 서블릿
- Today
- Total
늘
Junit5 테스트 동작 방식과 빈 주입 본문
@JdbcTest
@Sql("/schema.sql")
class RoomDaoTest {
@Autowired
private JdbcTemplate jdbcTemplate;
private RoomDao roomDao = new RoomDaoImpl(jdbcTemplate);
}
위 코드는 현재 NPE가 발생합니다.
반면에 아래 코드처럼 텍스트픽쳐스를 이용한 테스트는 정상 동작합니다.
@Sql("/schema.sql")
@JdbcTest
class PieceDaoTest {
@Autowired
private JdbcTemplate jdbcTemplate;
private PieceDao pieceDao;
@BeforeEach
void setUp(){
pieceDao = new PieceDaoImpl(jdbcTemplate);
}
}
JdbcTemplate은 빈으로 등록되어서 싱글톤으로 만들어져 있습니다.
반면에 Junit 테스트는 각 테스트 메서드마다 TestClass의 인스턴스를 만들고 각 인스턴스가 생성된 후 테스트가 실행한다고 합니다.
그렇기때문에 빈 객체에 대해서 스프링 IoC로 인해 개발자가 직접 인스턴스를 생성하지 않고 스프링이 관리해주는데, Junit 테스트 동작 방식이 각 테스트 메서드마다 필드에 선언된 객체에 대해서 직접 인스턴스를 생성하기 때문에 빈으로 관리되지 않아서, 빈 의존성 주입받는 게 실패해서 발생한 것이라고 추측을 한다.
class Sample {
private JdbcTemplate jdbcTemplate;
private RoomDao roomDao = new RoomDaoImpl(jdbcTemplate); // 1번
public Sample() { } // 2번
public setJdbcTemplate(JdbcTemplate jdbcTemplate) { // 3번
this.jdbcTemplate = jdbcTemplate;
}
}
class SampleApplication {
public static void main(String args) {
JdbcTemplate jdbcTemplate = new JdbcTemplate();
Sample sample = new Sample();
sample.setJdbcTemplate(jdbcTemplate);
}
}
이런 코드가 있다고 할 때, Sample 클래스에 있는 1~3번 코드의 실행 순서가 어떻게 될까요?위 내용을 먼저 생각해보신 후, 아래 코드를 다시 한번 보면 좋겠네요.
1,2,3번 순서대로 실행이 되었다. -> 모든 필드가 초기화 되고 그 후 생성자가 불러오는 것 같다
@JdbcTest
@Sql("/schema.sql")
class RoomDaoTest {
@Autowired
private JdbcTemplate jdbcTemplate;
private RoomDao roomDao = new RoomDaoImpl(jdbcTemplate);
jdbcTemplate 을 먼저 주입받고, 그 후에 RoomDao 를 생성하려면 어떻게 하면 좋을지 고민해볼 수 있겠죠.
jdbcTemplate 이 RoomDaoTest 에서 필요한 것인지, RoomDao 를 만들기 위해서만 필요한 것인지도 고민해볼 수 있을 것 같네요.
그렇기때문에 bean 객체에 대해서 스프링 IoC로 인해 개발자가 직접 인스턴스를 생성하지 않고 스프링이 관리 해주는데, Junit 테스트 동작 방식이 각 테스트 메서드마다 필드에 선언된 객체에 대해서 직접 인스턴스를 생성하기 때문에 빈으로 관리 되지 않아서, 빈 의존성 주입 받는게 실패해서 발생한 것이라고 봐도 될까요?
@Autowired
private JdbcTemplate jdbcTemplate;
private final RoomDao roomDao;
public RoomDaoTest(){
roomDao = new RoomDaoImpl(jdbcTemplate);
}
그래서
private JdbcTemplate jdbcTemplate;
private final RoomDao roomDao;
public RoomDaoTest(DataSource dataSource){
jdbcTemplate = new JdbcTemplate(dataSource);
roomDao = new RoomDaoImpl(jdbcTemplate);
}
위와 같이 생성자에서 받도록 실행을 했는데 생성자를 통해 주입하는 이 방식은 Junit5부터 안된다고 한다..

키워드는 Junit5 생성자 주입 에러라고 치면 나올것이다.
그런데 위 코드에서 생성자에 @Autowired만 붙이면 정상 동작이 되었다.
아무래도 Junit에서는 Jupiter가 빈들을 관리한다고 한다. 그래서 @Autowired를 명시적으로 적지 않으면 해당 스프링 빈을 찾지 못하므로 @Autowired를 적어서 스프링에게 해당 빈을 찾으라고 알려줘야 작동하는 것으로 보인다.
빈이 생성된 이후 추가로 호출되는 콜백들이 있는데요. Spring bean lifecycle, Spring bean hook 같은 키워드로 검색해보시면 도움이 될 것 같아요!추후에는 위 2개의 키워드도 찾아봐서 정리하려고 한다.
정리
필드에서 바로 주입받으려면 생성자가 실행된 이후에 일어나는 거라고 생각해서 필드 주입이 아닌 생성자 주입을 이용해야한다.
이때 Junit에서는 Jupiter가 빈들을 관리한다고 한다. 그래서 @Autowired를 명시적으로 적지 않으면 해당 스프링 빈을 찾지 못하므로 @Autowired를 적어서 스프링에게 해당 빈을 찾으라고 알려줘야 작동한다.
Reference
[java] 모범 사례 : setUp () 또는 선언시 JUnit 클래스 필드를 초기화 하시겠습니까? - 리뷰나라
이렇게 선언 할 때 클래스 필드를 초기화해야합니까? public class SomeTest extends TestCase { private final List list = new ArrayList(); public void testPopulateList() { // Add stuff to the list // Assert the list contains what I expect }
daplus.net
https://goodgid.github.io/How-JUnit-Works/
JUnit의 동작 방식
Index
goodgid.github.io
https://velog.io/@sdp1123/JUnit5-%EC%83%9D%EC%84%B1%EC%9E%90-%EC%A3%BC%EC%9E%85-%EC%98%A4%EB%A5%98
JUnit5 생성자 주입 에러
JUnit5로 테스트코드를 작성하면서 생성자를 통해서 DI하는 것, lombok을 이용한 DI도 에러가 발생했다.그런데 왜 lombok을 이용한 @Setter(onMethod\_ = {@Autowired}) 수정자 주입방식만 잘 되는걸까.. 도저히
velog.io
'우아한테크코스 4기' 카테고리의 다른 글
level 2 스프링 (0) | 2022.06.10 |
---|---|
리눅스 명령어와 권한 설정 chmod (0) | 2022.06.01 |
[Exception]checked Exception vs unchecked Exception (0) | 2022.04.25 |
우테코 Lv1 강의 정리 (0) | 2022.04.12 |
우아한 한 달 생활기 (0) | 2022.03.28 |