如何运行参数化的JUnit SpringJUnit4ClassRunner?

vohkndzv  于 2022-11-11  发布在  Spring
关注(0)|答案(4)|浏览(116)

由于@RunWith注解重复,以下代码无效:

@RunWith(SpringJUnit4ClassRunner.class)
@RunWith(Parameterized.class)
@SpringApplicationConfiguration(classes = {ApplicationConfigTest.class})
public class ServiceTest {
}

但是我如何将这两个注解结合使用呢?

hec6srdp

hec6srdp1#

您可以使用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();

    ...
clj7thdc

clj7thdc2#

至少有两个选项可以做到这一点:
1.遵循http://www.blog.project13.pl/index.php/coding/1077/runwith-junit4-with-both-springjunit4classrunner-and-parameterized/
您的测试需要看起来像这样:

@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);
     }
     ...
 }

1.有一个github项目https://github.com/mmichaelis/spring-aware-rule,它建立在以前的blog上,但是以一种通用的方式增加了支持

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

    ...
}

所以你可以有一个基类来实现其中的一种方法,所有的测试都从它继承。

sc4hvdpw

sc4hvdpw3#

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 transactionreinit dirty contextservlet 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;

  ...
}

如果您需要Spring context inside @Parameters静态方法为测试示例提供参数,请在这里查看我的答案How can I use the Parameterized JUnit test runner with a field that's injected using Spring?

tag5nh1u

tag5nh1u4#

自行处理应用程序上下文

对我起作用的是有一个“手动”管理应用程序上下文的@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();

相关问题