Whiteship's Note


Spring의 Test API에서 setUp과 tearDown

Spring/Chapter 8 : 2007.05.09 13:56


질문 : setUp() 와 tearDown() 메소드가 final로 되어 있는 테스트 클래스들이 대부분인데요. 그럼 Spring의 Test API를 사용할 때는 JUnit에서 각 테스트를 위해 매번 세팅하거나 자원을 돌려줘야 할 땐 어떻게 하나요??

답변 :

사용자 삽입 이미지
이 아래로 더 있을지도 모르겠지만 이 중에서 AbstractSpringContextTests 요거 부터 보겠습니다.
public class SpringTestTest extends AbstractSpringContextTests{

    @Override
    protected ConfigurableApplicationContext loadContext(Object arg0) throws Exception {
        throw new UnsupportedOperationException();
    }

    @Override
    protected void setUp() throws Exception {
        throw new UnsupportedOperationException();
    }

    @Override
    protected void tearDown() throws Exception {
        throw new UnsupportedOperationException();
    }
}

여기서는 JUnit의 setUp과 tearDown을 재정의 하여 사용할 수 있습니다.

그럼 한 단계 아래로 가서 AbstractSingleSpringContextTests를 보겠습니다. 어랏.. 여기서 부터는 위에서 사용한 setUp과 tearDown을 사용할 수 없습니다. final로 정의해 뒀네요.
사용자 삽입 이미지
어라.. "그럼 우리는 무얼 사용해야 되죠~?" 위 그림에 보이는 onSetUp()과 onTearDown()을 사용하면 됩니다.

public class SpringTestTest extends AbstractSingleSpringContextTests{

    @Override
    protected void onSetUp() throws Exception {
        throw new UnsupportedOperationException();
    }

    @Override
    protected void onTearDown() throws Exception {
        throw new UnsupportedOperationException();
    }
}

따라서 AbstractSingleSpringContextTests 이 클래스 하위에 있는 테스트 클레스들은 전부 위의 메소드들을 사용해야겠군요~

위 가정에 해당하는 증명은 AbstractSingleSpringContextTests 클레스에 있는 소스코드 일부로 할 수 있습니다.
    protected final void setUp() throws Exception {
        this.applicationContext = getContext(contextKey());
        prepareTestInstance();
        onSetUp();
    }

top


8.3. Integration testing

Spring/Chapter 8 : 2007.04.09 17:37


org.springframework.test 패키지에서 제공되는 기능들은 아래와 같습니다.
  • Spring IoC container caching between test case execution.
  • The pretty-much-transparent Dependency Injection of test fixture instances (this is nice).
  • Transaction management appropriate to integration testing (this is even nicer).
  • A number of Spring-specific inherited instance variables that are really useful when integration testing.
8.3.1. Context management and caching

여러 설정 파일들을 cashing하는 기능입니다. 이게 필요한 이유는 매번 테스트를 할 때마다 설정 파일들을 새로 읽어들이는 비용을 줄이기 위해서 입니다.

AbstractDependencyInjectionSpringContextTests 클래스를 상속하면 다음의 메소드를 꼭 구현하도록 abstract로 되어 있습니다.

protected abstract String[] getConfigLocations();

이 메소드에서 테스트에 필요한 bean설정 파일들(context)을 String 배열로 리턴하도록 구현해 주면 됩니다.

기본적으로 설정파일의 내용이 바꼈을 때만 다시 읽어 들이게 되고 명시적으로 다음 테스트를 하기 전에 다시 읽어 들이게 하고 싶다면 setDirty() 메소드를 사용합니다.

8.3.2. Dependency Injection of test fixtures

AbstractDependencyInjectionSpringContextTests 클래스를 사용하여 bean 설정 파일을 읽어 들이면 DI를 통해서 테스트할 때 필요한 멤버 변수에 값을 세팅할 수 있습니다.

by-type으로 autowiring 설정이 되어있습니다. 따라서 같은 타입의 bean이 여러개일 경우에는 적용이 되지 않을 것입니다.

테스트 클래스의 생성자에서 setPopulateProtectedVariables(true); 를 추가해 주면 protected 접근 지시자의 멤버 변수가 자동으로 세팅되도록 설정할 수 있습니다.

이 때는 autowiring을 사용한 것이 아니라 상속 받은 applicationContext 변수를 통해 직접 bean을 가져와서 세팅하게 됩니다.

8.3.3. Transaction management

DB에 접근하는 테스트를 할 때 문제는 DB에 테스트의 흔적이 남는다는 것인데요. AbstractTransactionalDataSourceSpringContextTests 클래스를 사용하면 테스트를 자동으로 트랜잭션 처리를 해주며 테스트가 끝날때 마다 DB를 롤백시켜줍니다.

이 클래스는 DataSource를 autowiring하게 되어 있으며 by-type이기 때문에 DataSource의 bean 이름은 상관없이 등록되어 있기만 하면 찾아서 DI합니다.

setComplete() 메소드를 사용하면 트랙잭션을 커밋시킬 수 있습니다.
endTransaction() 메소드를 사용하면 테스트 메소드가 끝나기 전에 트랜잭션을 종료시킬 수 있습니다.

8.3.4. Convenience variables

applicationContext :: AbstractDependencyInjectionSpringContextTests 클래스로 부터 상속받는 변수 입니다. bean을 직접 lookup 하거나 context 자체에 대한 테스트를 할 때 사용할 수 있습니다.

jdbcTemplate :: AbstractTransactionalDataSourceSpringContextTests 클래스로 부터 상속받는 변수 입니다.

8.3.5. Java5+ specific support

Java 5.0 이상에서 사용할 수 있는 AbstractAnnotationAwareTransactionalTests 클래스를 상요하면 다음의 어노테이션들을 사용할 수 있습니다.

@DirtiesContext :: 위에서 잠시 언급했었던 setDirty()와 같은 효과를 낼 수 있는 어노테이션으로 해당 테스트 메소드 위에 붙여주면 다음 테스트 메소드를 실행하기 전에 context들을 다시 읽어 들입니다.

@ExpectedException ::  이 어노테이션이 붙은 테스트 메소드에서 발생할 예외 객체 타입을 적어 줍니다. 만약 해당 테스트 메소드에서 해당 예외가 발생하면 테스트는 통과하고 그렇치 않으면 테스트는 실패합니다.

@NotTransactional :: 트랙잰션 관리 대상에서 제외합니다.

@Repeat :: 해당 테스트 메소드를 몇 번 반복해서 테스트할지 지정해 줄 수 있습니다.

위에서 언급했던 세 개의 클래스의 상속 구조 입니다.
사용자 삽입 이미지

top


Testing

Spring/Chapter 8 : 2007.04.09 08:37


8.1. Introduction

개발자 테스트(developer testing)은 소프트웨어 개발의 중요한 요소입니다.
IoC가 테스팅에 가져다 주는 이점과 Spring 프레임워크가 integration Testing에 가져다 주는 이점을 살펴 보겠습니다.

8.2. Unit testing

DI를 사용할 때의 장점은 이전 보다 컨테이너에 종속성이 훨씬 줄어들었다는 것입니다.
POJO를 테스트 하기 위해서는 어떤 컨테이너나 Spring이 필요 없습니다.
다른 객체와 연관되어 있을 경우 mock 객체를 사용하여 단위 테스트를 할 수 있습니다.
단위 테스트는 서버 설정, DB 설정 등의 환경 설정이 필요 없기 때문에 매우 빨리 할 수 있으며 생산성을 높여 줍니다.

8.3. Integration testing

하지만 어플리케이션 서버에 배포하거나 다른 infra와 통합하지 않은 상태에서 다음의 것들을 테스트할 수 있어야 합니다.
  • The correct wiring of your Spring IoC container contexts.

  • Data access using JDBC or an ORM tool. This would include such things such as the correctness of SQL statements / or Hibernate XML mapping files

They will be slower to run than unit tests, but much faster to run than the equivalent Cactus tests or remote tests relying on deployment to an application server.

8.3. Integration testing

8.4. Further Resources

top