JUnit领域中最有用的创新之一是Rule。 我在这里写了有关规则的文章 。 我在这里写了有关JUnit规则的用例 。 规则很棒。 借助JUnit 4.9,它们变得更好。
您可以将规则视为将测试的设置和拆卸封装在一个类中而不是两个方法中的一种方法。 但是规则也是一种修改执行测试方式的方法。 您可以多次运行测试,而不是一次。 或在二十个不同的线程中。 有趣的是,只有单个测试规则。 因此,如果您要坚持进行设置和拆卸的比较, 那么@Before和@After则在Rule中没有等效的@BeforeClass和@AfterClass 。
现在情况已经改变。 现在,您可以标注类型TestRule的公共静态字段与@ClassRule,它会表现就像是一整个测试类,而不是一个单一的测试定义的规则。 因此,对于需要为所有测试设置一次而不是为每个测试设置一次的东西而言,它是完美的选择。 让我们来看一个例子。
规则的实现可能如下所示:
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;public class LoggingRule implements TestRule {public class LoggingStatement extends Statement {private final Statement statement;public LoggingStatement(Statement aStatement, String aName) {statement = aStatement;}@Overridepublic void evaluate() throws Throwable {System.out.println("before: " + name);statement.evaluate();System.out.println("after: " + name);}}private final String name;public LoggingRule(String aName) {name = aName;}@Overridepublic Statement apply(Statement statement, Description description) {System.out.println("apply: " + name);return new LoggingStatement(statement, name);}}
大多数实现将由两部分组成: TestRule接口的实现和Statement接口的实现。
TestRule替换了以前不推荐使用的MethodRule接口。 这是因为新接口同时支持类级别和方法级别的Rule,因此必须进行一些更改。 TestRule有一个应用apply方法,该方法接受一条Statement并返回一条Statement 。 在执行Rule范围内的任何测试之前,将调用此方法。 传入的Statement实际上是可能执行的测试。 这里需要注意两件事:如果您的Rule与@ClassRule批注一起使用,则Statement可能并且将代表多个测试; 调用apply并不意味着Statement实际上会被执行。 由于您的规则返回的任何内容都可能传递给其他规则,因此在实际执行所包含的测试之前,可能会以各种方式对语句进行处理。 apply方法中要做的典型事情是将Statement包裹在一个新的Statement中 ,它将执行您所需的逻辑。
Statement接口具有单个方法评估 ,在正常情况下应执行一个测试或一堆测试。 因此,如果采用上述典型方法,则需要对包含的Statement 进行一些设置调用评估 ,并进行拆卸。 在上面提供的示例中,我在控制台上打印内容,以便可以看到以什么顺序调用内容。 该语句还传递了一个描述 ,其中包含有关测试的有用的元信息。 它包含名称,定义测试的类,方法名称并提供注释。 因此,您的“规则/声明”可以根据其操作所依据的测试方法来微调其行为。
使用此规则的测试类可能如下所示:
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;public class RuleTest {@ClassRulepublic static LoggingRule classRule = new LoggingRule("classrule");@Rulepublic static LoggingRule rule = new LoggingRule("rule");@Testpublic void testSomething() {System.out.println("In TestSomething");assertTrue(true);}@Testpublic void testSomethingElse() {System.out.println("In TestSomethingElse");assertTrue(true);}
}
对JUnit4.8规则的唯一更改是@ClassRule批注的存在。 请注意,同一类与@ClassRule和@Rule批注一起使用。
执行后,测试类的输出如下所示:
apply: classrule
before: classrule
apply: rule
before: rule
In TestSomething
after: rule
apply: rule
before: rule
In TestSomethingElse
after: rule
after: classrule
如您所见,首先将应用类级别的Rule并评估结果Statement 。 仅作为评估的一部分,才应用方法级别的“规则”并评估结果“ 语句” ,每次测试一次。
提醒您一句:小心在“规则”中使用正确的修饰符。 它们必须是公共的,并且类级别的规则必须是静态的。 取决于您做错了什么(以及您在什么环境中工作),导致的错误可能并不完全有用。 这被认为是一个错误,并且正在修复。
参考:来自Schauderhaft博客的JCG合作伙伴 Jens Schauder的 JUnit 4.9(测试版3)中的规则 。
相关文章 :
- Java工具:源代码优化和分析
- 框架使开发人员愚蠢吗?
- 每个程序员都应该知道的事情
- JDK中的设计模式
- Java最佳实践
翻译自: https://www.javacodegeeks.com/2011/09/rules-in-junit-49-beta-3.html