[토비의 스프링] 2장 테스트

테스트에 대한 사용법 같은 부분은 생략하고 새로 알게된 부분 위주로 정리

 

1장에서 살펴봤던 Ioc, DI 같은 객체지향 기술은 요구사항 변화에 유연하게 대응하는데도 도움이 되지만 테스트를 짜게 쉽게 만드는데도 도움이 된다. 그래서 테스트를 짜지 않는다면 스프링이 주는 가치중 많은 부분을 포기하는 셈이다.

ApplicationContext 매번생성되는 문제점

각 테스트가 독립적으로 실행되는것을 보다 확실하게 보장하기 위해서 매번 오브젝트를 생성한다.

public class UserDaoTest {
    private UserDao dao;

    @Before
    void setUp(){
        ApplicationContext context = new GenericXmlApplicationContext("applicationContext.xml")
        this.dao = context.getBean("userDao", UserDao.class);
    }

    @Test
    void test1(){}

    @Test
    void test2() {}

}

 

위 코드는 test1, test2 가 실행될때마다 새로운 오브젝트를 만들면서 @Before에 의해 setUp이 호출된다.
그래서 applicationContext도 여러번 생성하게 되는데 몇가지 이유로 안좋을수 있다.

  1. 빈 설정이 복잡해지면 어플리케이션 컨텍스트 생성에 시간이 필요해서 테스트 피드백이 느려진다
  2. 어떤 빈들은 자체적인 초기화 작업이 있어서 시간이 더 걸릴 수 있다
  3. 많은 리소스를 할당하거나 독자적인 스레드를 사용하는 빈이 있다면 리소스가 정리되지 않고 매번 어플리케이션 컨텍스트생성 할때마다 할당되면서 문제를 초래할 수 있다.

예제 추가하면 좋을듯

 

스프링 테스트 컨텍스트 프레임워크 적용하여 해결

테스트 컨텍스트 프레임워크 : 테스트에 사용되는 어플리케이션 컨텍스트를 생성하고 관리하고 테스트에 적용해주는 기능을 가진 프레임워크 => 어플리케이션 컨텍스트를 테스트에서도 쉽게 사용가능하게 도와줌

 

스프링은 JUnit을 이용하는 테스트컨텍스트 프레임워크를 제공해서 적용가능하다 

@RunWith(SpringJUnit4ClassRunner.class) // test 실행하는 runner를 spring 걸로 바꿈
@ContextConfiguration(locations="/applicationContext.xml")
class UserDaoTest {
	@Autowired
    UserDao dao;
   	...
}

 

이러면 매번생성하지 않고 하나의 어플리케이션 컨텍스트로 사용가능하다. 여러개의 클래스에서도 공유하기때문에 성능향상에 도움이 많이 됨

 

@DirtiesContext

일전에 CountingConnectionMaker를 별다른 코드 변경없이 추가한것처럼 테스트에서도 DI를 응용할수있다.

@RunWith(SpringJUnit4ClassRunner.class) // test 실행하는 runner를 spring 걸로 바꿈
@ContextConfiguration(locations = "/applicationContext.xml")
@DirtiesContext // 붙혀서 어플리케이션컨텍스트 바꿨다고 알려줌
class UserDaoTest {
    @Autowired
    UserDao dao;

    @Before
    public void setUp() {
        DataSource dataSource = new SingleConnectionDataSource("jdbc-url", ...);
        dao.setDataSource(dataSource);
    }
}

 

이렇게 테스트를 위한 SingleConnectionDataSource로 간단하게 바꿀수있는데 `@DirtiesContext` 를 붙혀서 같은 어플리케이션 컨텍스트를 사용하는 다른 테스트를 위해 해당 테스트가 끝나면 어플리케이션 컨텍스트를 삭제하고 다시만든다.