使用 TestExecutionListener 时,弹簧测试注射不起作用

2022-09-03 12:27:25

我想结合使用自定义,在我的测试数据库上运行 Liquibase 架构设置。我的工作正常,但是当我对我的类使用注释时,测试中DAO的注入不再有效,至少实例为空。TestExecutionListenerSpringJUnit4ClassRunnerTestExecutionListener

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

}

日志中没有错误,只是我的测试中有一个错误。我不明白使用 my 如何影响自动布线或注入。NullPointerExceptionTestExecutionListener


答案 1

我看了一下弹簧的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 {
    ...

更新:此处记录了该行为。

...或者,您可以通过使用@TestExecutionListeners显式配置类并从侦听器列表中省略 DependencyInjectionTestExecutionListener.class来完全禁用依赖注入。


答案 2

我建议考虑做这样的事情:

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

这样您就不需要知道需要哪些侦听器。我推荐这种方法,因为SpringBoot挣扎了几分钟,试图通过使用.DependencyInjectionTestExecutionListener.class


推荐