5

根据4.12 发行说明,可以同时使用 @Rule 和 @ClassRule 注释测试类的静态成员:

使用@Rule 和@ClassRule 注释的静态成员现在被认为是有效的。这意味着单个规则可用于在课程之前/之后(例如设置/拆除外部资源)和测试之间(例如重置外部资源)执行操作,

我想使用此功能在文件中所有测试的开头初始化资源,在每个测试之间对资源进行一些清理,并在所有测试完成后处理它。此资源当前由扩展ExternalResource的类表示。

在我的before方法after中,如何区分“所有测试之前/之后”和“每次测试之前/之后”?我是否需要使用不同的/自定义实现TestRule来完成此操作?

4

4 回答 4

8

您可以实现TestRule#apply并使用isTestisSuite方法Description来确定StatementTestRule的应用类型。

这是一个示例界面,您可以构建一个具有完整before, after, verify, beforeClass, afterClass,verifyClass类型行为的规则:

public interface CombinedRule extends TestRule {
    default Statement apply(Statement base, Description description) {
        if (description.isTest()) {
            return new Statement() {
                public void evaluate() throws Throwable {
                    before();
                    try {
                        base.evaluate();
                        verify();
                    } finally {
                        after();
                    }
                }
            };
        }
        if (description.isSuite()) {
            return new Statement() {
                public void evaluate() throws Throwable {
                    beforeClass();
                    try {
                        base.evaluate();
                        verifyClass();
                    } finally {
                        afterClass();
                    }
                }
            };
        }
        return base;
    }

    default void before() throws Exception {
        //let the implementer decide whether this method is useful to implement
    }

    default void after() {
        //let the implementer decide whether this method is useful to implement
    }

    /**
     * Only runs for Tests that pass
     */
    default void verify() {
        //let the implementer decide whether this method is useful to implement
    }

    default void beforeClass() throws Exception {
        before();
    }

    default void afterClass() {
        after();
    }

    /**
     * Only runs for Suites that pass
     */
    default void verifyClass() {
        verify();
    }
}
于 2018-02-13T04:40:59.513 回答
1

@Before用和注释的方法@After将在每次测试之前和之后运行,而用@BeforeClass和注释的方法@AfterClass将分别在类中的第一个/最后一个测试之前和之后运行。

a 的 before/after 方法@Rule在每个测试之前和之后执行,而 a 的 before/after 方法@ClassRule在整个测试类之前/之后运行。

只要处理程序方法对这两种情况做出正确反应,您就可以将 ExternalResource 用于@Ruleor情况。@ClassRule据我从文档中可以看出,没有办法区分规则类方法中的两个规则类别。如果您对这两种情况都使用规则类,则对两种情况都将应用相同的规则类。

于 2015-09-03T20:05:30.567 回答
0

您无法区分@BeforeClassand@Before@AfterClassand @After。有关添加此功能的原因的更多详细信息可以在拉取请求中找到。

于 2015-09-04T12:48:36.000 回答
0

您可以创建自己的规则来实现TestRuleMethodRule

public SharableExternalResource implements TestRule, MethodRule {

  public final Statement apply(
      final Statement base, Description description) {
    return
        new Statement() {
          @Override
          public void evaluate() throws Throwable {
            beforeClass();

            List<Throwable> errors = new ArrayList<Throwable>();
            try {
                base.evaluate();
            } catch (Throwable t) {
                errors.add(t);
            } finally {
                try {
                    afterClass();
                } catch (Throwable t) {
                    errors.add(t);
                }
            }
            MultipleFailureException.assertEmpty(errors);
          }
        };
  }

  public final Statement apply(
      Statement base, FrameworkMethod method, Object target) {
    return
        new Statement() {
          @Override
          public void evaluate() throws Throwable {
            before();

            List<Throwable> errors = new ArrayList<Throwable>();
            try {
                base.evaluate();
            } catch (Throwable t) {
                errors.add(t);
            } finally {
                try {
                    after();
                } catch (Throwable t) {
                    errors.add(t);
                }
            }
            MultipleFailureException.assertEmpty(errors);
          }
        };
  }

  public void beforeClass() throws Exception {
    // do nothing
  }

  protected void before() throws Exception {
    // do nothing
  }

  protected void after() throws Exception {
    // do nothing
  }

  public void afterClass() throws Exception {
    // do nothing
  }
}
于 2017-04-22T05:35:43.263 回答