【问题标题】:How to access the fields of a test class with in an Rule in JUnit如何在 JUnit 的规则中访问测试类的字段
【发布时间】:2012-03-22 15:22:58
【问题描述】:

我想编写一个 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)。

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

【问题讨论】:

    标签: java junit


    【解决方案1】:

    实现这一点的正确方法是让您的规则实现org.junit.rules.MethodRule(而不是TestRule)。 MethodRule 接口的apply() 方法有一个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()");
        }
    
    }
    

    【讨论】:

    【解决方案2】:

    怎么样:

    public class MyTestClass() {
      @Rule
      public TestRule MyEntityManagerInjectRule =
             new MyEntityManagerInjectRule(this); // pass instance to constructor
    
      //MyEntityManagerInjectRule "inject" the entity manager
      EntityManger em;
    
      @Test...
    }
    

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

    【讨论】:

    • 你如何使用@ClassRule 做到这一点?
    【解决方案3】:

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

    public class MyTestClass() {
      @Rule
      public MyEntityManagerRule rule = new MyEntityManagerRule();
    
      @Test
      public void firstTest() {
         doSomethingWith(rule.getEntityManager());
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2015-03-07
      • 1970-01-01
      • 1970-01-01
      • 2017-12-20
      • 1970-01-01
      • 2013-11-15
      • 1970-01-01
      • 1970-01-01
      • 2022-01-20
      相关资源
      最近更新 更多