问题描述
Spring Test 有助于回滚测试方法中对数据库所做的任何更改.这意味着不必在每个测试方法之前花时间删除/重新加载测试数据.
但是如果你使用@BeforeClass Junit 注释,那么这会强制数据加载器是静态的.这里探讨的一个问题:为什么 jUnit 的 fixtureSetup 必须是静态的?>
如果数据初始化方法是静态的,那么数据连接方法和数据源也必须是静态的......等等......强制一切都是静态的......这是行不通的.在这一点上,我问 - 当您必须为每个测试删除/重新加载测试数据时,Spring Test 回滚更改的能力有什么好处??!?!
一种有效的方法是创建一个数据初始化器"类,将它添加到一个也有你的数据源的测试 Spring 应用程序上下文中,然后连接这个应用程序上下文到您的测试中.这依赖于 Spring 在测试调用之间缓存应用程序上下文的事实.
例如,一个测试超类:
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations={"classpath:test-application-context.xml"})@交易公共抽象类 DataLoadingTest {@自动连线受保护的 DatabaseInitialiser 数据库初始化器;}
使用test-application-context.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"><属性名称=数据源"引用=数据源"/></bean></豆类>
和
public class DatabaseInitialiser extends JdbcDaoSupport {@PostConstruct公共无效负载(){//在此处初始化您的数据库:创建模式、使用 DBUnit 加载数据等.}}
在这个例子中:
- 所有依赖于数据库的测试都扩展了
DataLoadingTest
; - Spring 在第一次测试调用时初始化应用程序上下文;
- 通过
@PostConstruct
注解调用DatabaseInitialiser.load()
; - Spring 将应用程序上下文保存在缓存中;
- 在应用上下文中的
DatabaseInitialiser
中进一步测试调用,该应用上下文已经缓存; - 测试是事务性的,最后回滚到初始数据集.
同样地,DatabaseInitialiser
可以有一个带有 @PostDestroy
注释的方法,以在整个测试运行结束时执行任何必要的回滚.
Spring Test helpfully rolls back any changes made to the database within a test method. This means that it is not necessary to take the time to delete/reload the test data before each test method.
But if you use the @BeforeClass Junit annotation, then that forces the data loader to be static. A question that is explored here: Why must jUnit's fixtureSetup be static?
If the data initialization method is static, so must the data connection methods and the data source..and on and on...forcing everything to be static...which won't work. At which point, I ask - what good is Spring Test's ability to rollback changes when you have to delete/reload the test data anyway for every test??!?!
One approach that works is to create a "data initialiser" class, add it to a test Spring application context that also has your data source, and wire this application context into your tests. This relies on the fact that Spring caches the application context between test invocations.
For example, a test superclass:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:test-application-context.xml"})
@Transactional
public abstract class DataLoadingTest {
@Autowired
protected DatabaseInitialiser databaseInitialiser;
}
With test-application-context.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>
And
public class DatabaseInitialiser extends JdbcDaoSupport {
@PostConstruct
public void load() {
// Initialise your database here: create schema, use DBUnit to load data, etc.
}
}
In this example:
- all tests that rely on the database extend
DataLoadingTest
; - Spring initialises the application context upon first test invocation;
- this calls
DatabaseInitialiser.load()
, via the@PostConstruct
annotation; - Spring keeps the application context in a cache;
- further test invocations wire in the
DatabaseInitialiser
from the application context, which is already cached; - tests are transactional, and roll back at the end to the initial data set.
Likewise, DatabaseInitialiser
can have a method annotated @PostDestroy
to perform any rollback necessary at the end of the whole test run.
这篇关于如何使用 Spring Test 为每个案例加载一次 DBUnit 测试数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!