这是第一个没有 JUnit 4.12 参数化工厂的解决方案,下面是一个改进的解决方案。
没有事务支持的静态上下文
让 Spring 使用 TestContextManager 类进行所有配置解析和自动装配。
诀窍是使用假测试实例来获取自动装配的字段并将它们传递给将有效运行的参数化测试。
但请记住 prepareTestInstance() 进行自动装配,但不管理测试事务以及 beforeTestMethod() 和 afterTestMethod() 处理的其他好东西。
@RunWith(Parameterized.class)
@ContextConfiguration(locations = {"/test-context.xml", "/mvc-context.xml"})
@WebAppConfiguration
@ActiveProfiles("test-profile")
public class MyTest {
@Parameters
public static Collection<Object[]> params() throws Exception {
final MyTest fakeInstance = new MyTest();
final TestContextManager contextManager = new TestContextManager(MyTest.class);
contextManager.prepareTestInstance(fakeInstance);
final WebApplicationContext context = fakeInstance.context;
// Do what you need with Spring context, you can even access web resources
final Resource[] files = context.getResources("path/files");
final List<Object[]> params = new ArrayList<>();
for (Resource file : files) {
params.add(new Object[] {file, context});
}
return params;
}
@Parameter
public Resource file;
@Autowired
@Parameter(1)
public WebApplicationContext context;
}
但是,如果您有很多自动装配的字段,则会出现一个缺点,因为您必须手动将它们传递给数组参数。
完全支持 Spring 的参数化工厂
JUnit 4.12 引入了ParametersRunnerFactory,它允许结合参数化测试和 Spring 注入。
public class SpringParametersRunnerFactory implements ParametersRunnerFactory {
@Override
public Runner createRunnerForTestWithParameters(TestWithParameters test) throws InitializationError {
final BlockJUnit4ClassRunnerWithParameters runnerWithParameters = new BlockJUnit4ClassRunnerWithParameters(test);
return new SpringJUnit4ClassRunner(test.getTestClass().getJavaClass()) {
@Override
protected Object createTest() throws Exception {
final Object testInstance = runnerWithParameters.createTest();
getTestContextManager().prepareTestInstance(testInstance);
return testInstance;
}
};
}
}
可以将工厂添加到以前的测试类中以提供完整的 Spring 支持,例如 test transaction、reinit dirty context 和 servlet test。当然,不再需要将假测试实例中的自动装配字段传递给参数化测试。
@UseParametersRunnerFactory(SpringParametersRunnerFactory.class)
@RunWith(Parameterized.class)
@ContextConfiguration(locations = {"/test-context.xml", "/mvc-context.xml"})
@WebAppConfiguration
@Transactional
@TransactionConfiguration
public class MyTransactionalTest {
@Parameters
public static Collection<Object[]> params() throws Exception {
final MyTransactionalTest fakeInstance = new MyTransactionalTest();
final TestContextManager contextManager = new TestContextManager(MyTransactionalTest.class);
contextManager.prepareTestInstance(fakeInstance);
final WebApplicationContext context = fakeInstance.context;
// Do what you need with Spring context, you can even access web resources
final Resource[] files = context.getResources("path/files");
final List<Object[]> params = new ArrayList<>();
for (Resource file : files) {
params.add(new Object[] {file});
}
return params;
}
@Parameter
public Resource file;
@Autowired
private WebApplicationContext context;
}