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

时间:2012-03-22 15:22:58

标签: java junit

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

这样的事情:

public class MyTestClass() {

  @Rule
  MyEntityManagerInjectRule = new MyEntityManagerInjectRule():

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

  @Test...
}

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

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

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

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

3 个答案:

答案 0 :(得分:16)

实现这一目标的正确方法是使您的规则实施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()");
                }
            }
        };
    }
}

使用@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()");
    }

}

答案 1 :(得分:12)

怎么样:

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

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

  @Test...
}

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

答案 2 :(得分:4)

有一种不同的方法:规则提供EntityManager而不是注入它。

public class MyTestClass() {
  @Rule
  public MyEntityManagerRule rule = new MyEntityManagerRule();

  @Test
  public void firstTest() {
     doSomethingWith(rule.getEntityManager());
  }
}