如何使用JUnit中的规则访问测试类的字段

Ral*_*lph 14 java junit

我想编写一个JUnit @Rule(版本4.10)来设置一些对象(实体管理器),并通过将它"注入"变量使它们在测试中可用.

像这样的东西:

public class MyTestClass() {

  @Rule
  MyEntityManagerInjectRule = new MyEntityManagerInjectRule():

  //MyEntityManagerInjectRule "inject" the entity manager
  EntityManger em;

  @Test...
}
Run Code Online (Sandbox Code Playgroud)

问题是我不知道如何获取MyTestClassMyEntityManagerInjectRule中的当前实例(扩展TestRule),因为它只有一个方法. Statement apply(Statement base, Description description);

在Description内,只有MyTestClass类,但没有用于测试的实例.

另一种方法是使用org.junit.rules.MethodRule但不推荐使用.之前和之后不足以完成此任务,因为那时我需要将代码复制到测试中,并且它们或多或少都被弃用了.(参见Block4JClassRunner.withBefores/withAfters).

所以我的问题是如何在不使用弃用的东西的情况下访问测试类实例.

acd*_*ior 17

实现这一目标的正确方法是使规则实现org.junit.rules.MethodRule(而不是TestRule).接口的apply()方法MethodRule有一个target参数,它包含对测试类的当前实例引用(当然,每次执行一个方法时它都是一个不同的实例).

MethodRule

public class ExampleMethodRule implements MethodRule {

    @Override
    public Statement apply(final Statement base,
                                         FrameworkMethod method, Object target) {
        System.out.println("ExampleMethodRule#apply()" +
                           "\n\t base: " + base +
                           "\n\t method (current test method): " + method +
                           "\n\t target (current test class instance): "+target);

        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                System.out.println("->before evaluate()");
                try {
                    base.evaluate();
                } finally {
                    System.out.println("->after evaluate()");
                }
            }
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

示例测试类使用 @Rule

public class ExampleTest {

    @Rule
    public ExampleMethodRule exampleMethodRule = new ExampleMethodRule();

    @BeforeClass
    public static void beforeClass() {
        System.out.println("@BeforeClass");
    }
    @AfterClass
    public static void afterClass() {
        System.out.println("@AfterClass");
    }

    @Before
    public void before() {
        System.out.println("@Before");
    }
    @After
    public void after() {
        System.out.println("@After");
    }

    @Test
    public void aa() {
        System.out.println("method aa()");
    }
    @Test
    public void bb() {
        System.out.println("method bb()");
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 自4.11起,MethodRule不再被弃用:https://github.com/junit-team/junit/pull/519 (4认同)

Mat*_*ell 12

怎么样:

public class MyTestClass() {
  @Rule
  public TestRule MyEntityManagerInjectRule =
         new MyEntityManagerInjectRule(this); // pass instance to constructor

  //MyEntityManagerInjectRule "inject" the entity manager
  EntityManger em;

  @Test...
}
Run Code Online (Sandbox Code Playgroud)

只需将测试类实例添加到构造函数中即可@Rule.请注意分配顺序.

  • 你如何用@ClassRule做到这一点? (2认同)