Подтвердить что ты не робот

Spring тестовая инъекция не работает при использовании TestExecutionListener

Я хочу использовать пользовательский TestExecutionListener в сочетании с SpringJUnit4ClassRunner для запуска установки схемы Liquibase в моей тестовой базе данных. Мой TestExecutionListener отлично работает, но когда я использую аннотацию в моем классе, инъекция DAO под тестом больше не работает, по крайней мере экземпляр имеет значение null.

@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
        ...
    }
}

Слушатель довольно прост:

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

}

В журнале нет ошибок, только NullPointerException в моем тесте. Я не вижу, как использование моего TestExecutionListener влияет на автоувеличивание или инъекцию.

4b9b3361

Ответ 1

Я просмотрел журналы spring DEBUG и обнаружил, что когда я опускаю свой собственный TestExecutionListener spring, устанавливается на 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: Поведение зарегистрировано здесь.

... Кроме того, вы можете полностью отключить инъекцию зависимостей, явно сконфигурировав свой класс с помощью @TestExecutionListeners и опустив DependencyInjectionTestExecutionListener.class из списка слушателей.

Ответ 2

Я бы рекомендовал подумать о том, чтобы сделать что-то вроде:

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

чтобы вам не нужно было знать, какие слушатели требуются. Я рекомендую этот подход, потому что в течение нескольких минут с помощью SpringBoot вы пытаетесь заставить его работать правильно, используя DependencyInjectionTestExecutionListener.class.