1일1배움/Spring (김영한 님)
[23/04/13] @Autowired가 붙은 ApplicationContext 인스턴스 변수
kim chan jin
2023. 4. 13. 10:51
@RunWith(SpringJUnit4ClassRunner.class) // JUnit 확장기능은 테스트 전에 딱 한번 테스트용 ApplicationContext를 만들고 관리
@ContextConfiguration(location="/applicationContext.xml") // 읽어야 할 구성 정보의 위치
public class AutowiredInstanceTest { // 테스트 클래스 -> 테스트 오브젝트
@Autowired
private ApplicationContext ac;
// 스프링 애플리케이션 컨텍스트(AnnotationConfigApplicataionContext 등)는 (?) 초기화할 때 자기 자신도 빈으로 등록한다
// 따라서 애플리케이션 컨텍스트에는 ApplicationContext 타입의 빈이 존재하는 셈이고 테스트용 ApplicationContext DI도 가능
// 매번 테스트 오브젝트가 만들질 때마다 단 하나의 테스트용 ApplicationContext가 주입됨
private UserDao userDao;
private User user1;
private User user2;
private User user3;
@Before
public void setUp() {
this.userDao = this.ac.getBean("userDao", UserDao.class);
this.user1 = new User("KCJ", "김찬진", "1234");
this.user2 = new User("AGJ", "안금장", "1234");
this.user3 = new User("GSW", "강승원", "1234");
System.out.println(this.ac); // @RunWith, @ContextConfiguration 덕분에 테스트 오브젝트에서 단 하나의 테스트용 ApplicationContext를 공유함
System.out.println(this); // 2. @Test 메소드마다 테스트 오브젝트를 생성하므로 매번 새로운 메모리 주소가 출력
// 1. 테스트 클래스(class hello.core.CharTest2)에서 @Test가 붙은 public이고 void형이며 파라미터가 없는 테스트 메소드를 모두 찾음
// 2. 테스트 클래스의 오브젝트를 하나 만든다
// 3. @Before가 붙은 메소드가 있으면 실행한다
// 4. @Test가 붙은 메소드를 하나 호출하고 테스트 결과를 저장
// 5. @After가 붙은 메소드가 있으면 실행한다
// 6. 나머지 테스트 메소드에 대해 2번 ~ 5번을 반복
// 7. 모든 테스트의 결과를 종합해서 돌려줌
}
@Test
public void addAndGet() {
// test 코드
}
@Test
public void count() {
// test 코드
}
@Test
public void getUserFailure() {
// test 코드
}
}
나는 ApplicationContext ac 라는 참조변수를 빈에 등록한 적이 없다.
@Bean을 적어준 적이 없다는 것이다.
심지어 생성자 DI도, 수정자 메소드 DI도 한 적이 없다.
근데 어떻게 참조변수 ac에 테스트용 ApplicationContext가 DI 되는걸까?
그 이유는 참조변수 ac가 초기화될 때,
즉 JUnit 확장기능(@RunWith, @ContextConfiguration)이 단 하나의 테스트용 ApplicationContext 를 만들고 이를 참조변수 ac에 주입을 해줄 때,
참조변수 ac 자기자신도 빈으로 등록되기 때문이다.
그래서 컨테이너 속에서 ac에게 테스트용 ApplicationContext가 DI 되는 것이다.
그럼 결과적으로 테스트를 할 때마다 매번 테스트용 ApplicationContext(컨테이너)를 만드는 것이 아니라 단 하나의 테스트용 ApplicationContext를 가지고 테스트를 할 수 있게 된다.
단, 잊지 말아야 할 것은 테스트용 ApplicationContext는 하나를 공유할지라도 테스트 객체(여기선 AutowiredInstanceTest 객체)는 매번 만들어진다는 것이다.
@Test 어노테이션이 붙은 메소드를 하나씩 실행하기 전 테스트 객체가 매번 만들어지는 이유는 테스트들이 독립적으로 실행되기 위한 목적이다.