Java 如何使用参数化运行 JUnit SpringJUnit4ClassRunner?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28560734/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to run JUnit SpringJUnit4ClassRunner with Parametrized?
提问by membersound
The following code is invalid due to duplicate @RunWith
annotation:
由于重复@RunWith
注释,以下代码无效:
@RunWith(SpringJUnit4ClassRunner.class)
@RunWith(Parameterized.class)
@SpringApplicationConfiguration(classes = {ApplicationConfigTest.class})
public class ServiceTest {
}
But how can I use these two annotations in conjunction?
但是如何结合使用这两个注释呢?
采纳答案by mavarazy
There are at least 2 options to do that:
至少有 2 个选项可以做到这一点:
Your test needs to look something like this:
@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); } ... }
There is a github project https://github.com/mmichaelis/spring-aware-rule, which builds on previous blog, but adds support in a generalized way
@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(); ... }
您的测试需要如下所示:
@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(); ... }
So you can have a basic class implementing one of the approaches, and all tests inheriting from it.
因此,您可以拥有一个实现其中一种方法的基本类,以及从它继承的所有测试。
回答by keyoxy
You can use SpringClassRule and SpringMethodRule - supplied with Spring
您可以使用 SpringClassRule 和 SpringMethodRule - 随 Spring 提供
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();
...
回答by Arnor
There is another solution with JUnit 4.12 without the need of Spring 4.2+.
JUnit 4.12 还有另一种解决方案,无需 Spring 4.2+。
JUnit 4.12 introduces ParametersRunnerFactorywhich allow to combine parameterized test and Spring injection.
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;
}
};
}
}
The factory can be added to test class to give full Spring support like test transaction, reinit dirty contextand servlet test.
可以将工厂添加到测试类中以提供完整的 Spring 支持,例如测试事务、重新初始化脏上下文和servlet 测试。
@UseParametersRunnerFactory(SpringParametersRunnerFactory.class)
@RunWith(Parameterized.class)
@ContextConfiguration(locations = {"/test-context.xml", "/mvc-context.xml"})
@WebAppConfiguration
@Transactional
@TransactionConfiguration
public class MyTransactionalTest {
@Autowired
private WebApplicationContext context;
...
}
If you need Spring context inside @Parametersstatic method to provide parameters to test instances, please see my answer here How can I use the Parameterized JUnit test runner with a field that's injected using Spring?.
如果您需要在@Parameters静态方法中使用Spring 上下文来为测试实例提供参数,请在此处查看我的答案如何使用带有使用 Spring 注入的字段的参数化 JUnit 测试运行程序?.
回答by manuelvigarcia
Handle application context by yourself
自己处理应用上下文
What worked for me was having a @RunWith(Parameterized.class)
test class that managed the application context "by hand".
对我有用的是有一个@RunWith(Parameterized.class)
“手动”管理应用程序上下文的测试类。
To do that I created an application context with the same string collection that would be in the @ContextConfiguration
. So instead of having
为此,我创建了一个应用程序上下文,该上下文与@ContextConfiguration
. 所以,而不是拥有
@ContextConfiguration(locations = { "classpath:spring-config-file1.xml",
"classpath:spring-config-file2.xml" })
I had
我有
ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[] {
"classpath:spring-config-file1.xml", "classpath:spring-config-file2.xml" });
And for each @Autowired I needed I fetched it by hand from the created context:
对于我需要的每个 @Autowired,我从创建的上下文中手动获取它:
SomeClass someBean = ctx.getBean("someClassAutowiredBean", SomeClass.class);
Do not forget to close the context at the end:
最后不要忘记关闭上下文:
((ClassPathXmlApplicationContext) ctx).close();