简体   繁体   English

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

[英]How to access the fields of a test class with in an Rule in JUnit

I want to write an JUnit @Rule (version 4.10) to setup some objects (an Entity Manager) and make them available in the test, by "injecting" it into an variable. 我想编写一个JUnit @Rule(版本4.10)来设置一些对象(实体管理器),并通过将它“注入”变量使它们在测试中可用。

Something like this: 像这样的东西:

public class MyTestClass() {

  @Rule
  MyEntityManagerInjectRule = new MyEntityManagerInjectRule():

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

  @Test...
}

The Problem is that I do not know how to get the current instance of MyTestClass in the MyEntityManagerInjectRule (extends TestRule), because it has only one method. 问题是我不知道如何在MyEntityManagerInjectRule(扩展TestRule)中获取MyTestClass的当前实例,因为它只有一个方法。 Statement apply(Statement base, Description description);

Within Description there is only the class MyTestClass but not the instance used for the test. 在Description内,只有MyTestClass类,但没有用于测试的实例。

An alternative would be using org.junit.rules.MethodRule but this is deprecated. 另一种方法是使用org.junit.rules.MethodRule,但不推荐使用。 Before and After are not sufficient for this task, because then I would need to copy the code to the tests, and they are more or less deprecated too. 之前和之后不足以完成此任务,因为那时我需要将代码复制到测试中,并且它们或多或少都被弃用了。 (See Block4JClassRunner.withBefores / withAfters). (参见Block4JClassRunner.withBefores / withAfters)。

So my question in how could I access the test class instance without using deprecated stuff. 所以我的问题是如何在不使用弃用的东西的情况下访问测试类实例。

The proper way to achieve that is to make your rule implement org.junit.rules.MethodRule (not TestRule ). 实现这一目标的正确方法是使你的规则实现org.junit.rules.MethodRule (而不是TestRule )。 The apply() method of the MethodRule interface has a target argument, which holds a reference to the current instance of the test class (of course, it is a different instance each time a method is executed). MethodRule接口的apply()方法有一个target参数,它保存对测试类当前实例引用 (当然,每次执行一个方法时它都是一个不同的实例)。

Example MethodRule 示例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()");
                }
            }
        };
    }
}

Example test class using @Rule 使用@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()");
    }

}

How about: 怎么样:

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

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

  @Test...
}

Just add the test class instance to the constructor for the @Rule . 只需将测试类实例添加到@Rule的构造函数中。 Just be careful of the order of assignment. 请注意分配顺序。

There is a different approach: the rule provides the EntityManager instead of injecting it. 有一种不同的方法:规则提供EntityManager而不是注入它。

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

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

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

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