如何在 Spring 测试中注册 ApplicationEnvironmentPreparedEvent

How to register a ApplicationEnvironmentPreparedEvent in Spring Test

我有一个 @SpringBootTest,我需要通过 ApplicationEnvironmentPreparedEvent 通知我创建一个数据库文件(如果它不存在),因为我的应用程序数据库试图连接到它但它不存在。

我是通过 SpringApplicationBuilder 执行此操作的,但在 JUnit 中我无法访问此生成器。这是我当前的 main 代码:

SpringApplicationBuilder appBuilder = new SpringApplicationBuilder();
appBuilder.headless(false);
appBuilder.listeners(new ApplicationListener<ApplicationEvent>() {
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ApplicationEnvironmentPreparedEvent) {
            Environment env = ((ApplicationEnvironmentPreparedEvent) event).getEnvironment();
            String datasourceUrl = env.getProperty(RepositoryConfig.JDBC_URL_PROPERTY);

            File db = FirebirdUtil.extractDatabaseFile(datasourceUrl);
            if (db != null) {
                String user = env.getProperty(RepositoryConfig.JDBC_USER_PROPERTY);
                String password = env.getProperty(RepositoryConfig.JDBC_PASSWORD_PROPERTY);

                // this will create the FDB file if it doesn't exists
                FirebirdUtil.createDatabaseifNotExists(db, user, password);
            }
        }
    }
});

如何在 Enviroment 准备就绪时通知我,以便在数据源配置之前读取 JDBC URL 并创建用于测试的数据库文件?

因为在测试中没有 main 方法 运行,所以你的监听器在测试中不可用。
首先,您需要将侦听器提取到 class 以供将来在测试中使用(例如 MyListener)。
第二次使用自定义加载器在应用程序中声明侦听器。

我只是检查它是否适合我。 这是测试的例子:

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(loader = CustomLoader.class)
public class DemoApplicationTests {

public static class CustomLoader extends SpringBootContextLoader {

    @Override
    protected SpringApplication getSpringApplication() {
        SpringApplication app = super.getSpringApplication();
        app.addListeners(new MyListener());
        return app;
    }
}

另一种方法是利用 @Import 注释将 ApplicationListener bean 注入到应用程序上下文中:

@RunWith(SpringRunner.class)
@SpringBootTest
@Import(ApplicationTests.ApplicationEventListener.class)
public class ApplicationTests {

    public static class ApplicationEventListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
        @Override
        public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
            // do required staff
        }
    }
}