Usage and Idioms——Rules
初识Rules
首先,让我们先来认识一下 Rule。在 JUnit4.7 中已经引入了新特性 Rule,总的来说,Rule 是 JUnit 的一种扩展机制,它可以很灵活的添加或重新定义每个测试方法或类的行为,测试人员能重新利用或扩展 JUnit 提供的规则,也可以定义自己的规则。
举个栗子O(∩_∩)O~ :DigitalAssetManagerTest
分布系统中提供的基本Rules
TemporaryFolder Rule:也是在 JUnit 4.7 引入的,测试可以创建文件与目录并在测试运行结束后(不管成功还是失败)将其删除。这对于那些与文件系统打交道而且独立运行的测试来说很有用,默认情况下源文件如果没有被删除不抛出异常。
newFile() 方法创建一个随机名字的新文件。
newFolder() 方法创建一个随机名字的新文件夹。
newFolder(String[]) 方法会递归地创建新文件夹。
举个栗子O(∩_∩)O~:HasTempFolder
ExternalResource Rules:
ExternalResource为子类提供了两个接口,分别是进入测试之前和退出测试之后,一般它是作为对一些资源在测试前后的控制,如Socket的开启与关闭、Connection的开始与断开、临时文件的创建与删除等。如果ExternalResource用在@ClassRule注解字段中,before()方法会在所有@BeforeClass注解方法之前调用;after()方法会在所有@AfterClass注解方法之后调用,不管在执行@AfterClass注解方法时是否抛出异常。如果ExternalResource用在@Rule注解字段中,before()方法会在所有@Before注解方法之前调用;after()方法会在所有@After注解方法之后调用。
TemporaryFolder是对ExternalResource的一个实现,它在before()方法中在临时文件夹中创建一个随机的文件夹,以junit开头;并在after()方法将创建的临时文件夹清空,并删除该临时文件夹。另外TemporaryFolder还提供了几个方法以在新创建的临时文件夹中创建新的文件、文件夹。
举个栗子O(∩_∩)O~:UsesExternalResource
ErrorCollector Rule:在单元测试中发现第一个问题后,该机制允许测试继续运行。
举个栗子O(∩_∩)O~:UsesErrorCollectorTwice
Verifier Rule:Verifier是在所有测试已经结束的时候,再加入一些额外的逻辑,如果额外的逻辑通过,才表示测试成功,否则,测试依旧失败,即使在之前的运行中都是成功的。
Verifier是在所有测试已经结束的时候,再加入一些额外的逻辑,如果额外的逻辑通过,才表示测试成功,否则,测试依旧失败,即使在之前的运行中都是成功的。Verify可以为一些很多测试方法加入一些公共的验证逻辑。当Verifier应用在@Rule注解字段中,它在所偶@After注解方法运行完后,会调用verify()方法,如果verifier()方法验证失败抛出异常,则该测试方法的testFailure事件将会被触发,导致该测试方法失败;当Verifier应用在@ClassRule时,它在所有的@AfterClass注解的方法执行完后,会执行verify()方法,如果verify失败抛出异常,将会触发关于该测试类的testFailure,此时测试类中的所有测试方法都已经运行成功了,却在最后收到一个关于测试类的testFailure事件,这确实是一个比较诡异的事情,因而@ClassRule中提到ErrorCollector(Verifier)不可以用在@ClassRule注解中,否则其行为为定义;更一般的@ClassRule注解的字段运行时不能抛异常,不然其行为是未定义的。
ErrorCollector是对Verifier的一个实现,它可以在运行测试方法的过程中收集错误信息,而这些错误信息知道最后调用ErrorCollector的verify()方法时再处理。其实就目前来看,我很难想象这个需求存在的意义,因为即使它将所有的错误信息收集在一起了,在事件发布是,它还是会为每个错误发布一次testFailure事件(参考EachTestNotifier的实现),除非有一种需求是即使测试方法在运行过程的某个点运行出错,也只是先记录这个错误,等到所有逻辑运行结束后才去将这个测试方法运行过程中存在的错误发布出去,这样一次运行就可以知道测试代码中存在出错的地方。ErrorCollector中还提供了几个收集错误的方法:如addError()、checkThat()、checkSucceeds()等。这里的checkThat()方法用到了hamcrest框架中的Matcher,这部分的内容将在Assert小节中详细介绍。
TestWatchman/TestWatcher Rules:从JUIT 4.9开始,TestWatcher取代了TestWatcherman,TestWatcher实现了TestRule而不是MethodRule。TestWatcherman是在JUnit4.7中引入的,使用MethodRule,现在不赞成使用。TestWatcher和TestWatcherman都是用来记录测试行为的类。
举个栗子O(∩_∩)O~:WatchmanTest
TestName Rule : 允许将测试方法名传入测试方法中。举个栗子O(∩_∩)O~:NameRuleTest
Timeout Rule:与@test 中的timeout注释有相同的功能,只不过该规则适用全局。举个栗子O(∩_∩)O~:HasGlobalTimeout
ExpectedException Rules :允许展现测试内部可预期异常的错误类型与错误信息。举个栗子O(∩_∩)O~:HasExpectedException
ClassRule: JUnit用于标注Rule的注解包括@Rule和@ClassRule,区别在于作用域不同@Rule的作用域是测试方法,@ClassRule则是测试Class。举个栗子O(∩_∩)O~:UsesExternalResource
RuleChain:RuleChain提供一种将多个TestRule串在一起执行的机制,它首先从outChain()方法开始创建一个最外层的TestRule创建的Statement,而后调用round()方法,不断向内层添加TestRule创建的Statement。举个栗子O(∩_∩)O~:UseRuleChain