복붙노트

[SPRING] 봄 : 단위 및 통합 테스트

SPRING

봄 : 단위 및 통합 테스트

나는 봄을 사용하여 단위 테스트와 통합 테스트를 설정하는 베스트 프랙티스를 찾고있다.

보통 3 종류의 테스트를 사용합니다.

현재 저는 두 번째 범주의 테스트 만 있습니다. 까다로운 부분입니다. 기본 테스트 클래스를 다음과 같이 설정했습니다.

@ContextConfiguration(locations = { "/my_spring_test.xml" })
public abstract class AbstractMyTestCase extends AbstractJUnit4SpringContextTests

그리고 "unit"테스트는 다음과 같습니다 :

public class FooTest extends AbstractMyTestCase

autowired 속성.

다른 (통합 테스트) 환경에서 테스트를 실행하는 가장 좋은 방법은 무엇입니까? 테스트를 서브 클래스 화하고 ContextConfiguration을 재정의 하시겠습니까?

@ContextConfiguration(locations = { "/my_spring_integration_test.xml" })
public class FooIntegrationTest extends FooTest

이 도구가 작동할까요? (저는 현재 여기에서 쉽게 테스트 할 수 없습니다)? 이 접근 방식의 문제점은 "@ContextConfiguration (locations = {"/my_spring_integration_test.xml "})"이 많이 복제된다는 것입니다.

어떤 제안?

문안 인사, 플로리안

해결법

  1. ==============================

    1.나는 GenericXmlContextLoader를 확장했다.

    나는 GenericXmlContextLoader를 확장했다.

    공용 클래스 MyContextLoader는 GenericXmlContextLoader {

    그리고

    보호 된 String [] generateDefaultLocations (Class clazz)

    메서드를 사용하여 SystemProperty (-Dtest.config =)로 지정할 수있는 디렉토리의 구성 파일 이름을 수집합니다.

    또한 다음 방법을 수정하여 위치를 수정하지 않았습니다.

    @Override
    protected String[] modifyLocations(Class<?> clazz, String... locations) {
        return locations;
    }
    

    이 컨텍스트 로더를 다음과 같이 사용합니다.

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(loader = MyContextLoader.class)
    public class Test { .... }
    

    구성 파일의 소스를 나타내는 SystemProperty로 테스트를 실행하면 완전히 다른 구성을 사용할 수 있습니다.

    물론 SystemProperty의 사용은 구성 위치를 지정하는 유일한 전략입니다. generateDefaultLocations ()에서 원하는대로 할 수 있습니다.

    편집하다:

    이 솔루션을 사용하면 다른 속성뿐만 아니라 완전히 다른 애플리케이션 컨텍스트 구성 (예 : 모의 객체)을 사용할 수 있습니다. "classpath"위치에 모든 것을 배포하기 위해 빌드 단계가 필요하지 않습니다. 내 구체적인 구현은 또한 시스템 특성이 주어지지 않으면 (프로젝트의 모든 개발자를위한 특정 테스트 환경을 쉽게 유지할 수 있도록) 구성 디렉토리 (src / test / resources / {user})를 찾기 위해 기본적으로 사용자 이름을 사용했습니다.

    속성 자리 표시 자의 사용은 여전히 ​​가능하고 권장됩니다.

    편집하다:

    Spring Version 3.1.0은 내 솔루션과 유사한 XML 프로파일 / 환경 추상화를 지원하며 다양한 환경 / 프로파일에 대한 구성 파일의 선택을 가능하게합니다.

  2. ==============================

    2.나는이 버전으로 갈 것이다 :

    나는이 버전으로 갈 것이다 :

    ContextConfiguration(locations = { "/my_spring_test.xml" })
    public abstract class AbstractMyTestCase extends AbstractJUnit4SpringContextTests
    

    my_spring_test.xml에서는 PropertyPlaceHolderConfigurer 메커니즘을 사용합니다.

    JPA의 예 :

    <context:property-placeholder
        system-properties-mode="OVERRIDE" 
        location="classpath:test.properties" />
    
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="${test.database.driver}" />
        <property name="url" value="${test.database.server}" />
        <property name="username" value="${test.database.user}" />
        <property name="password" value="${test.database.password}" />
    </bean>
    
    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="test" />
        <property name="dataSource" ref="dataSource" />
        <property name="persistenceXmlLocation"
                 value="classpath:META-INF/persistence.xml" />
        <property name="jpaVendorAdapter">
    <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
        <property name="showSql" value="false" />
        <property name="generateDdl" value="${test.database.update}" />
        <property name="database" value="${test.database.databasetype}" />
    </bean>
        </property>
    </bean>
    

    이제 인 - 메모리 및 실제 통합 테스트를위한 클래스 경로에 다른 버전의 test.properties가 있어야합니다. 물론 각 드라이버 클래스가 있어야합니다. 시스템 속성을 설정하여 속성 값을 덮어 쓸 수도 있습니다.

    이것을 maven으로 준비하고 싶다면, maven으로 파일을 복사하는 것이 쉽지 않은 것을 알 수 있습니다. 코드를 실행하는 방법이 필요합니다. 표준 선택 사항은 maven-antrun-plugin과 gmaven-maven-plugin입니다.

    두 가지 구성 파일 (예 : src / main / config에 두 개의 플러그인 실행을 추가합니다. 하나는 위상 생성 테스트 리소스이고 다른 하나는 위상 사전 통합 테스트입니다. 다음은 GMaven 버전입니다.

    <plugin>
        <groupId>org.codehaus.gmaven</groupId>
        <artifactId>gmaven-plugin</artifactId>
        <version>1.3</version>
        <executions>
            <execution>
                <phase>pre-integration-test</phase>
                <goals>
                    <goal>execute</goal>
                </goals>
                <configuration>
                <source>
                new File(
                   pom.build.testOutputDirectory,
                   "test.properties"
                ).text = new File(
                           pom.basedir,
                           "src/main/config/int-test.properties"
                ).text;
                </source>
                </configuration>
            </execution>
            <execution>
                <phase>generate-test-resources</phase>
                <goals>
                    <goal>execute</goal>
                </goals>
                <configuration>
                <source>
                new File(
                   pom.build.testOutputDirectory,
                   "test.properties"
                ).text = new File(
                           pom.basedir,
                           "src/main/config/memory-test.properties"
                ).text;
                </source>
                </configuration>
            </execution>
        </executions>
    </plugin>
    
  3. ==============================

    3.나는 property-placeholder 태그 인 Spring 3.x 컨텍스트를 사용하여 성공하지 못했다. 나는 속성 파일과 함께 오래된 패션 bean 태그를 사용했고 내 코드와 데이터베이스 사이에 연결을 설정할 수 있었다.

    나는 property-placeholder 태그 인 Spring 3.x 컨텍스트를 사용하여 성공하지 못했다. 나는 속성 파일과 함께 오래된 패션 bean 태그를 사용했고 내 코드와 데이터베이스 사이에 연결을 설정할 수 있었다.

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="/com/my/package/database.properties"/>
    </bean>
    
    
    <bean id="myDatasource" class="oracle.ucp.jdbc.PoolDataSourceFactory" 
        factory-method="getPoolDataSource">
        <property name="URL" value="${JDBC_URL}"/>
        <property name="user" value="${JDBC_USERNAME}"/>
        <property name="password" value="${JDBC_PASSWORD}"/>
        <property name="connectionFactoryClassName"   
          value="oracle.jdbc.pool.OracleConnectionPoolDataSource"/>
        <property name="ConnectionPoolName" value="SCDB_POOL"/>
        <property name="MinPoolSize" value="5"/>
        <property name="MaxPoolSize" value="50"/>
        <property name="connectionWaitTimeout" value="30"/>
        <property name="maxStatements" value="100"/>
    </bean>
    

    다음은 속성 파일의 예입니다.

    JDBC_URL=jdbc:oracle:thin:@myDB:1521:mySchema
    JDBC_USERNAME=username
    JDBC_PASSWORD=password
    

    그런 다음 JUnit 테스트를 다음과 같이 설정합니다.

    @ContextConfiguration(locations = {"/com/my/pkg/test-system-context.xml"})
    @RunWith(SpringJUnit4ClassRunner.class)
    public class HeaderDaoTest {
    
        @Autowired
        HeaderDao headerDao;
    
        @Test
        public void validateHeaderId() {
            int headerId = 0;
    
            headerId = headerDao.getHeaderId();
    
            assertNotSame(0,headerId);
        }
    
    }
    

    그것은 저에게 효과적 이었지만, 모든 사람들은 조금 다른 방식으로 일을합니다. 희망이 도움이됩니다.

  4. ==============================

    4.최근에 같은 문제가 발생하여 @ContextConfiguration 주석에 대한 설명서를 보았을 때 inheritLocations 옵션을 발견했습니다.

    최근에 같은 문제가 발생하여 @ContextConfiguration 주석에 대한 설명서를 보았을 때 inheritLocations 옵션을 발견했습니다.

    예를 들어 내 수업에 추가하면

    @ContextConfiguration(locations = { "/my_spring_integration_test.xml" }, inheritLocations=false)
    public class FooIntegrationTest extends FooTest
    

    ContextConfiguration을 원하는대로 재정의 할 수 있다는 것을 알게되었습니다.

  5. from https://stackoverflow.com/questions/4593530/spring-unit-and-integration-tests by cc-by-sa and MIT license