Junit 如何使用Spring测试在每个情况下加载DBUnit测试数据一次
SpringTest有助于回滚测试方法中对数据库所做的任何更改。这意味着在每个测试方法之前,无需花费时间删除/重新加载测试数据 但是如果使用@BeforeClass Junit注释,则会强制数据加载程序是静态的。这里探讨的一个问题是:Junit 如何使用Spring测试在每个情况下加载DBUnit测试数据一次,junit,dbunit,spring-test,Junit,Dbunit,Spring Test,SpringTest有助于回滚测试方法中对数据库所做的任何更改。这意味着在每个测试方法之前,无需花费时间删除/重新加载测试数据 但是如果使用@BeforeClass Junit注释,则会强制数据加载程序是静态的。这里探讨的一个问题是: 如果数据初始化方法是静态的,那么数据连接方法和数据源也必须是静态的。而且,不断地……强制所有内容都是静态的……这是行不通的。在这一点上,我要问-当您必须为每个测试删除/重新加载测试数据时,Spring测试回滚更改的能力有什么好处 Spring测试和DbUnit是两
如果数据初始化方法是静态的,那么数据连接方法和数据源也必须是静态的。而且,不断地……强制所有内容都是静态的……这是行不通的。在这一点上,我要问-当您必须为每个测试删除/重新加载测试数据时,Spring测试回滚更改的能力有什么好处 Spring测试和DbUnit是两个优秀的框架。但是把它们结合起来是没有意义的。由于Spring Test在连接上执行回滚,因此它会在之后进行清理,而DbUnit会在
@Before
方法中清理并插入测试数据
如果不依赖任何动态数据,请使用Spring,否则请使用dbUnit 我们广泛地将DBUnit与Spring测试结合使用。但是我们不使用DBUnit功能在测试结束时删除数据 我们在@Before方法中为测试数据插入了一组DBUnit插入,以初始化测试。然后,当测试完成时,我们让spring回滚功能将数据库恢复到其原始状态
我们遇到的最大问题是每次测试之前都必须加载DBUnit数据,这可能会对性能造成重大影响。我们使用DBUnit的大多数测试都是只读的,根据某些预定义的行为测试应用程序的行为。因此,我们习惯于创建主测试,然后在同一事务中批量运行所有细粒度测试。一种有效的方法是创建一个“数据初始化器”类,将其添加到同样具有数据源的test Spring应用程序上下文中,并将此应用程序上下文连接到测试中。这取决于Spring在测试调用之间缓存应用程序上下文这一事实 例如,测试超类:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:test-application-context.xml"})
@Transactional
public abstract class DataLoadingTest {
@Autowired
protected DatabaseInitialiser databaseInitialiser;
}
使用测试应用程序上下文.xml
:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dataSource" .../>
<bean class="DatabaseInitialiser">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
在本例中:
- 所有依赖于数据库的测试都会扩展
李>DataLoadingTest
- Spring在第一次测试调用时初始化应用程序上下文李>
- 这将通过
注释调用@PostConstruct
DatabaseInitialiser.load()李>
- Spring将应用程序上下文保存在缓存中李>
- 进一步的测试调用从已经缓存的应用程序上下文连接到
数据库初始化器
李>
- 测试是事务性的,并在最后回滚到初始数据集
DatabaseInitialiser
可以有一个带注释的方法@postdirection
,以在整个测试运行结束时执行任何必要的回滚。方法运行,正如其名称所示,在每个测试的事务开始之前运行。如果在这种方法中,您可以检测是否加载了测试数据,则可以在需要时加载数据
不过要注意,数据会留在(内存中)数据库中,以供后续所有测试使用
我们使用它来加载“静态”数据,在生产环境中,这些数据在启动数据库时也会引导到数据库中。这样,我们实际上在测试中使用完全相同的代码和数据,而不是依赖于可能过时的(DbUnit)导出 您可以创建一个数据初始值设定项“bean”,因为配置只运行一次。它遵循与主要答案相同的原则,但代码和类较少
@Configuration
class DBUnitTest_Config {
protected String PATH = "";
@Bean
public DataSetConfig setupData(DataSource dataSource) throws SQLException {
DataSetExecutorImpl executor = DataSetExecutorImpl.instance(new ConnectionHolderImpl(dataSource.getConnection()));
DataSetConfig dataSetConfig = new DataSetConfig(PATH);
executor.createDataSet(dataSetConfig);
return dataSetConfig;
}
}
我发现DBUnit从XML加载数据库表的能力非常方便。弹簧测试有这样的功能吗?是的,我认为垫子是错的。从XML文件加载测试数据对使用Spring进行db测试是一个很好的好处。事实上,这正是我解决问题的方法,我只是忘记了将代码/答案放回SO中。谢谢你花时间为下一个家伙做这件事。听起来不错,但实际上另一个类的“@PostConstruct”在数据库初始化器之前运行,所以它没有用。谢谢你的帮助。@united expression:你能详细介绍一下吗?你指的是哪一类?在我的示例中,Spring在测试类之前初始化数据库初始化器,测试类在问题中概述的Cass中工作。我有另一个由Spring管理的类,由'@Component'注释,它的'@PostConstruct'方法访问数据库,以便在数据库初始化器之前初始化该类。目前的解决方法是为另一个类使用自定义注释,但更倾向于使用更好的解决方案。谢谢。我喜欢你的方法,我更进一步了。看看下面……这是一个坏习惯。你觉得这个检查过的解决方案怎么样?
@Configuration
class DBUnitTest_Config {
protected String PATH = "";
@Bean
public DataSetConfig setupData(DataSource dataSource) throws SQLException {
DataSetExecutorImpl executor = DataSetExecutorImpl.instance(new ConnectionHolderImpl(dataSource.getConnection()));
DataSetConfig dataSetConfig = new DataSetConfig(PATH);
executor.createDataSet(dataSetConfig);
return dataSetConfig;
}
}