在使用SchemaExport.execute
的JUnit / Spring测试运行期间,负责触发Hibernate的hbm2ddl.auto
(考虑到SpringJUnit4ClassRunner
已激活)的Spring事件是什么?
(考虑到所有这些,我可以拥有几个具有相同上下文配置的测试套件,并且可以缓存弹簧上下文......)
我问这个问题是因为我已经设置了一个Spring监听器(用作数据填充器),如下所示:
@Profile({ Profiles.DEFAULT, Profiles.CLOUD, Profiles.TEST, Profiles.DEV })
@Component
public class BootstrapLoaderListener implements ApplicationListener<ContextRefreshedEvent>, ResourceLoaderAware, Ordered {
private static final Logger log = Logger.getLogger(BootstrapLoaderListener.class);
@Override
public int getOrder() {
return HIGHEST_PRECEDENCE;
}
@Override
@Transactional
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
initApplication();
}
...
我有两个集成测试套件(SpringJUnit4ClassRunner
),它们共享相同的上下文配置,因此共享相同的缓存应用程序上下文。
但是我注意到当两个测试套件中的第二个在第一个之后运行时,上面的应用程序监听器不会得到通知。
总结一下:
答案 0 :(得分:1)
ContextRefreshedEvent
的Javadoc明确指出它是......
ApplicationContext
初始化或刷新时引发的事件。
因此,只有在BootstrapLoaderListener
启动(即初始化或刷新)时才会调用ApplicationContext
,这只会发生一次:当Spring TestContext Framework加载测试的上下文时。但是,如果您使用@DirtiesContext
,则ApplicationContext
可能会多次重新创建。
换句话说,您目睹的关于听众的行为是设计和预期的。
至于为什么你的架构会第二次创建,这仍然是一个谜。通常这不应该发生。例如,如果您使用的是Spring LocalSessionFactoryBean
或LocalSessionFactoryBuilder
,那么每个工厂只会在初始化或刷新SessionFactory
时创建一次Hibernate ApplicationContext
。
也许您有一些非标准配置导致SessionFactory
被多次创建,但我无法根据您提供的信息来判断。
但是,如果您希望在每次测试之前调用设置代码(仅仅因为它不会自动多次调用),则建议不要使用ApplicationListener
来设置测试数据库。如果您确实想在测试中使用ApplicationListener
,则可以在ContextRefreshedEvent
或ApplicationContext
方法中为@Before
中的@BeforeTransaction
个人发起测试
作为替代方案(可能更好的解决方案),您可以通过以下方式之一以编程方式在@Before
或@BeforeTransaction
方法中调用SQL脚本:
SimpleJdbcTestUtils.executeSqlScript(...)
方法(在Spring 2.5 - 3.x上)JdbcTestUtils.executeSqlScript(...)
方法之一(在Spring 4.x及更高版本上)ScriptUtils.executeSqlScript(...)
方法之一(在Spring 4.0.3及更高版本上)executeSqlScript(...)
或AbstractTransactionalJUnit4SpringContextTests
AbstractTransactionalTestNGSpringContextTests
方法
ResourceDatabasePopulator
和DatabasePopulatorUtils
从尚未发布的Spring 4.1开始,您可以通过@Sql
注释以声明方式调用SQL脚本。
Sam(Spring TestContext Framework的作者)
P.S。您还可以使用上面提到的相同选项实现自定义TestExecutionListener
以编程方式调用SQL脚本。