这是我能够开始工作的示例。
我利用@ContextConfiguration 注释来使用3 个不同的文件启动上下文。 “MyJobConfiguration.xml”包含我不会在此处包含的生产批处理作业定义(与此问题无关)。 “BatchIntegrationTests.xml”是用于我所有批处理集成测试的通用上下文配置。它处理覆盖数据源以使用自动生成模式的内存数据库。同样,不包括在内。
“BatchJobIT.xml”是我设置我将使用的实际存储库填充器的地方。不幸的是,repository:unmarshaller-populator 标签需要指定locations 属性;所以我需要提供一个“虚拟”xml 文件(com/example/anyData.xml),当应用程序上下文启动时,存储库填充器将加载该文件。我还指定使用 XStream Unmarshaller 并提供它在测试期间可能遇到的任何别名。
BatchJobIT.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
*
* Additional Configuration for BatchJobIT integration tests.
*
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:repository="http://www.springframework.org/schema/data/repository"
xmlns:oxm="http://www.springframework.org/schema/oxm"
xsi:schemaLocation="http://www.springframework.org/schema/data/repository http://www.springframework.org/schema/data/repository/spring-repository-1.5.xsd
http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<repository:unmarshaller-populator
id="populator" locations="classpath:com/example/anyData.xml"
unmarshaller-ref="xstreamMarshaller" />
<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="aliases">
<props>
<prop key="domainObjects">java.util.List</prop>
<prop key="domainObject">com.example.domain.MyObject</prop>
</props>
</property>
</bean>
</beans>
然后,实际的测试类就非常简单了……在@Setup 中进行了一些小技巧。首先,我@Autowirepopulator 来获得对它的引用。我还需要对应用程序上下文的引用,所以我也需要@Autowire。
对于本示例,我在类路径中搜索由测试类名称和测试方法名称限定的 test-data.xml 文件。然后,我将该测试数据文件设置为填充器上的资源位置并触发ContextRefreshedEvent,这会导致填充器重新填充它的存储库。
BatchJobIT.java
package com.example;
import static org.junit.Assert.assertNotNull;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.data.repository.init.UnmarshallerRepositoryPopulatorFactoryBean;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* This integration test will test a Spring Batch job.
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/modules/MyJobConfiguration.xml", "BatchIntegrationTests.xml", "BatchJobIT.xml" })
public class BatchJobIT {
@Autowired
private EntityManagerFactory entityManagerFactory;
@Autowired
private UnmarshallerRepositoryPopulatorFactoryBean populator;
//Keep track of the test name for use within the test methods
@Rule
public TestName name = new TestName();
@Autowired
private ApplicationContext applicationContext;
@Before
public void setUp() throws Exception {
//Dynamically build the path to the test-data file. In this example, classpath will be searched for
//'com/example/BatchJobIT.testBatchJob.test-data.xml'
StringBuilder testDataFileName = new StringBuilder();
testDataFileName.append(this.getClass().getCanonicalName());
testDataFileName.replace(0, testDataFileName.length(), testDataFileName.toString().replaceAll("\\.", "/"));
testDataFileName.append(".");
testDataFileName.append(name.getMethodName());
testDataFileName.append(".test-data.xml");
//Set new resource location
populator.getObject().setResourceLocation(testDataFileName.toString());
//Send a context refreshed event to the populator which causes it to re-populate repositories
populator.onApplicationEvent(new ContextRefreshedEvent(applicationContext));
}
@After
public void tearDown() throws Exception {
//Delete test data from database
EntityManager em = entityManagerFactory.createEntityManager();
try {
em.getTransaction().begin();
em.createNativeQuery("TRUNCATE SCHEMA public AND COMMIT").executeUpdate();
if (em.getTransaction().isActive()) {
em.getTransaction().commit();
}
} catch (Exception e) {
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
throw e;
} finally {
em.close();
}
}
@Test
public void testBatchJob() throws Exception {
//Uncomment to launch hsqldb manager to inspect that data was loaded
//org.hsqldb.util.DatabaseManagerSwing.main(new String[] { "--url", "jdbc:hsqldb:mem:testdb" });
//Run test
assertNotNull(populator);
}
}
这确实感觉有点老套,但我认为它足够强大,直到我可以像@NealeU 建议的那样仔细查看 spring-test-dbunit。