2013-03-29 2 views
13

SpringJUnit4ClassRunner과 함께 사용자 정의 TestExecutionListener을 사용하여 테스트 데이터베이스에서 Liquibase 스키마 설정을 실행하고 싶습니다. 내 TestExecutionListener 잘 작동하지만 내 클래스에 주석을 사용하면 테스트중인 DAO 주입이 더 이상 작동하지 않습니다. 적어도 인스턴스는 null입니다. TestExecutionListener를 사용할 때 스프링 테스트 주입이 작동하지 않습니다.

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { "file:src/main/webapp/WEB-INF/applicationContext-test.xml" }) 
@TestExecutionListeners({ LiquibaseTestExecutionListener.class }) 
@LiquibaseChangeSet(changeSetLocations={"liquibase/v001/createTables.xml"}) 
public class DeviceDAOTest { 

    ... 

    @Inject 
    DeviceDAO deviceDAO; 

    @Test 
    public void findByCategory_categoryHasSubCategories_returnsAllDescendantsDevices() { 
     List<Device> devices = deviceDAO.findByCategory(1); // deviceDAO null -> NPE 
     ... 
    } 
} 

리스너

은 매우 간단하다 : 오류가 단지 NullPointerException 내 테스트에서, 로그에 없습니다

public class LiquibaseTestExecutionListener extends AbstractTestExecutionListener { 

    @Override 
    public void beforeTestClass(TestContext testContext) throws Exception { 
     final LiquibaseChangeSet annotation = AnnotationUtils.findAnnotation(testContext.getTestClass(), 
       LiquibaseChangeSet.class); 
     if (annotation != null) { 
      executeChangesets(testContext, annotation.changeSetLocations()); 
     } 
    } 

    private void executeChangesets(TestContext testContext, String[] changeSetLocation) throws SQLException, 
      LiquibaseException { 
     for (String location : changeSetLocation) { 
      DataSource datasource = testContext.getApplicationContext().getBean(DataSource.class); 
      DatabaseConnection database = new JdbcConnection(datasource.getConnection()); 
      Liquibase liquibase = new Liquibase(location, new FileSystemResourceAccessor(), database); 
      liquibase.update(null); 
     } 
    } 

} 

. 내 TestExecutionListener의 사용이 자동 와이어 링 또는 주입에 어떻게 영향을 주는지는 알 수 없습니다.

답변

20

봄 DEBUG 로그를 살펴본 결과, 내 자신의 TestExecutionListener 봄을 생략하면 DependencyInjectionTestExecutionListener가 제자리에 설정된다는 것을 알게되었습니다. @TestExecutionListeners를 사용하여 테스트에 주석을 추가 할 때 리스너가 덮어 쓰기됩니다.

그래서 난 그냥 내 사용자 정의 하나를 명시 적으로 DependencyInjectionTestExecutionListener을 추가하고 모든 작동합니다 :

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { "file:src/main/webapp/WEB-INF/applicationContext-test.xml" }) 
@TestExecutionListeners(listeners = { LiquibaseTestExecutionListener.class, 
    DependencyInjectionTestExecutionListener.class }) 
@LiquibaseChangeSet(changeSetLocations = { "liquibase/v001/createTables.xml" }) 
public class DeviceDAOTest { 
    ... 

UPDATE : 동작은 here를 설명되어 있습니다.

... 또는 @TestExecutionListeners로 클래스를 명시 적으로 구성하고 리스너 목록에서 DependencyInjectionTestExecutionListener.class를 생략함으로써 종속성 삽입을 모두 비활성화 할 수 있습니다.

+1

맞습니다. @ TestExecutionListeners를 통해 사용자 정의 'TestExecutionListener'를 지정하면 모든 기본 TestExecutionListener가 암시 적으로 대체됩니다. 물론,이 기능은 잘 설명되어 있지 않을 수 있습니다. 따라서 JIRA 문제를 자유롭게 열어 문서 개선을 요청하십시오. ;) –

+1

@SamBrannen : 실제로 그것은 암시 적으로 설명되어 있습니다. 내 업데이트 답변을 참조하십시오. – nansen

+2

필자가 작성한 이후 인용 한 텍스트를 잘 알고 있습니다. ;)하지만 ... 당신이 발생한 시나리오를 명시 적으로 설명하지는 않습니다. 그렇기 때문에 문서를 개선하기 위해 JIRA 티켓을 개설 할 것을 제안했습니다. –

3

난 그냥 같은 일을 고려하는 것이 좋습니다 :

@TestExecutionListeners(
     mergeMode =TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS, 
     listeners = {MySuperfancyListener.class} 
) 

을 그래서 당신이 요구되는 청취자 알 필요가 없습니다. SpringBoot가 단지 DependencyInjectionTestExecutionListener.class을 사용하여 올바르게 작동하도록 노력하면서 몇 분 동안 고생했기 때문에이 방법을 권장합니다.

관련 문제