由于重复的@RunWith
注释,以下代码无效:
@RunWith(SpringJUnit4ClassRunner.class)
@RunWith(Parameterized.class)
@SpringApplicationConfiguration(classes = {ApplicationConfigTest.class})
public class ServiceTest {
}
但是我如何结合使用这两个注释?
答案 0 :(得分:75)
你可以使用Spring提供的SpringClassRule和SpringMethodRule
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.springframework.test.context.junit4.rules.SpringClassRule;
import org.springframework.test.context.junit4.rules.SpringMethodRule;
@RunWith(Parameterized.class)
@ContextConfiguration(...)
public class MyTest {
@ClassRule
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
@Rule
public final SpringMethodRule springMethodRule = new SpringMethodRule();
...
答案 1 :(得分:34)
至少有两种选择:
您的测试需要看起来像这样:
@RunWith(Parameterized.class)
@ContextConfiguration(classes = {ApplicationConfigTest.class})
public class ServiceTest {
private TestContextManager testContextManager;
@Before
public void setUpContext() throws Exception {
//this is where the magic happens, we actually do "by hand" what the spring runner would do for us,
// read the JavaDoc for the class bellow to know exactly what it does, the method names are quite accurate though
this.testContextManager = new TestContextManager(getClass());
this.testContextManager.prepareTestInstance(this);
}
...
}
有一个github项目https://github.com/mmichaelis/spring-aware-rule,它建立在之前的博客上,但是以一种通用的方式增加了支持
@SuppressWarnings("InstanceMethodNamingConvention")
@ContextConfiguration(classes = {ServiceTest.class})
public class SpringAwareTest {
@ClassRule
public static final SpringAware SPRING_AWARE = SpringAware.forClass(SpringAwareTest.class);
@Rule
public TestRule springAwareMethod = SPRING_AWARE.forInstance(this);
@Rule
public TestName testName = new TestName();
...
}
因此,您可以拥有一个实现其中一种方法的基本类,以及从中继承的所有测试。
答案 2 :(得分:1)
JUnit 4.12还有另一种解决方案,不需要Spring 4.2 +。
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 {
@Autowired
private WebApplicationContext context;
...
}
如果您需要@Parameters静态方法中的Spring上下文来提供测试实例的参数,请在How can I use the Parameterized JUnit test runner with a field that's injected using Spring?此处查看我的答案。
答案 3 :(得分:0)
对我有用的是拥有一个@RunWith(Parameterized.class)
测试类,该类可以“手动”管理应用程序上下文。
为此,我使用与@ContextConfiguration
中相同的字符串集合创建了一个应用程序上下文。所以不用
@ContextConfiguration(locations = { "classpath:spring-config-file1.xml",
"classpath:spring-config-file2.xml" })
我有
ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] {
"classpath:spring-config-file1.xml", "classpath:spring-config-file2.xml" });
对于每个@Autowired,我需要从创建的上下文中手动获取它:
SomeClass someBean = ctx.getBean("someClassAutowiredBean", SomeClass.class);
不要忘记最后关闭上下文:
((ClassPathXmlApplicationContext) ctx).close();