简体   繁体   English

如何使用Parametrized运行JUnit SpringJUnit4ClassRunner?

[英]How to run JUnit SpringJUnit4ClassRunner with Parametrized?

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? 但是我如何结合使用这两个注释呢?

You can use SpringClassRule and SpringMethodRule - supplied with Spring 您可以使用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();

    ...

There are at least 2 options to do that: 至少有两个选项可以做到这一点:

  1. Following http://www.blog.project13.pl/index.php/coding/1077/runwith-junit4-with-both-springjunit4classrunner-and-parameterized/ 关注http://www.blog.project13.pl/index.php/coding/1077/runwith-junit4-with-both-springjunit4classrunner-and-parameterized/

    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); } ... } 
  2. There is a github project https://github.com/mmichaelis/spring-aware-rule , which builds on previous blog, but adds support in a generalized way 有一个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. 因此,您可以拥有一个实现其中一种方法的基本类,以及从中继承的所有测试。

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 ParametersRunnerFactory which 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 context and 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 @Parameters static 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测试运行器? .

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)是拥有一个@RunWith(Parameterized.class)测试类,它“手动”管理应用程序上下文。

To do that I created an application context with the same string collection that would be in the @ContextConfiguration . 为此,我创建了一个应用程序上下文,其中包含与@ContextConfiguration相同的字符串集合。 So instead of having 所以没有

@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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM