2013-03-29 26 views
13

Chcę użyć niestandardowego TestExecutionListener w połączeniu z SpringJUnit4ClassRunner, aby uruchomić konfigurację schematu Liquibase w mojej testowej bazie danych. Moja TestExecutionListener działa dobrze, ale kiedy używam adnotacji na mojej klasie, wstrzyknięcie testowanego DAO nie działa, przynajmniej instancja jest pusta.Wstrzyknięcie testu sprężyny nie działa podczas korzystania z 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 
     ... 
    } 
} 

Słuchacz jest dość prosta:

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); 
     } 
    } 

} 

Brak błędów w dzienniku, tylko NullPointerException w moim teście. Nie rozumiem, w jaki sposób korzystanie z mojego telefonu TestExecutionListener wpływa na proces autowykonywania lub wstrzykiwania.

Odpowiedz

20

Zerknąłem na logi DEBUG ze sprężyną i odkryłem, że kiedy pominę moją własną sprężynę TestExecutionListener, ustawi się DependencyInjectionTestExecutionListener. Podczas dodawania adnotacji do testu za pomocą @TestExecutionListeners słuchacz zostaje nadpisany.

Więc po prostu dodał DependencyInjectionTestExecutionListener wprost z mojego niestandardowej jeden i wszystko działa poprawnie:

@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: zachowanie jest udokumentowane here.

... Ewentualnie można wyłączyć iniekcji zależność zupełnie jawnie konfigurowania klasę z @TestExecutionListeners i pomijając DependencyInjectionTestExecutionListener.class z listy słuchaczy.

+1

To prawda: jeśli podasz 'TestExecutionListener' za pomocą' @ TestExecutionListeners', możesz domyślnie zastąpić wszystkie domyślne TestExecutionListeners. Oczywiście funkcja ta nie jest dobrze udokumentowana. Możesz więc otworzyć problem JIRA, aby poprosić o udoskonalenie dokumentacji. ;) –

+1

@SamBrannen: Właściwie jest to udokumentowane - być może nieco implicite. Zobacz moją zaktualizowaną odpowiedź. – nansen

+2

Doskonale zdaję sobie sprawę z tekstu, który cytowałeś, od kiedy go napisałem. ;) Ale ... to nie opisuje dokładnie napotkanego scenariusza. Dlatego zaproponowałem, abyś otworzył bilet JIRA, aby ulepszyć dokumentację. –

3

Polecam rozważyć po prostu robi coś takiego:

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

tak, że nie trzeba wiedzieć, które słuchacze są wymagane. Polecam to podejście, ponieważ przez kilka minut zmagałem się z programem SpringBoot, próbując sprawić, by działało poprawnie, używając tylko DependencyInjectionTestExecutionListener.class.

Powiązane problemy