JUnit 是流行的 Java 单元测试框架,近日 JUnit Lambda 团队宣布发布新的主要版本—— JUnit 5 alpha 版本。通过一个成功的众筹活动允许全职开发人员工作在该项目上,JUnit 5 的主要变化集中在去除了JUnit 4 带给开发人员的普遍问题,同时修改了框架以便于将来的变更。与构建工具和集成开发环境的整合仍需要一些额外的工作。
JUnit 5 已经适应了开发人员每天编写单元测试的方式,开发人员对此非常感激。例如,尽管 JUnit FAQ 传统上反对在一个单元测试中放多个断言,但是一些轶事证据表明,开发人员倾向于这么做。一个测试中包括多个断言的风险是一旦其中一个失败,测试执行就会停止,不会执行其他的断言。因此,JUnit 5 支持分组断言(grouped assertions),所有的断言都会被执行,即使其中一个或多个断言失败:
@Test void groupedAssertions() { assertAll("address", () -> assertEquals("John", address.getFirstName()), () -> assertEquals("User", address.getLastName()) ); }
来自 JUnit 5 用户指南的示例代码。
让人不满意的另一个常见原因是对测试异常的支持,因为 JUnit 4 中提供的几种方式都不能满足开发人员的需求。人们可以用 @Test 注解中的”expected“选项表示期望抛出的异常类型;但是,对于更复杂的断言,这是不够灵活的,比如在抛出的异常中检查异常信息。在这种情况下,开发人员可以用 @Rule 和 ExpectedException,这确实支持使用匹配器来检查异常信息;然而,即使是 ExpectedException 也不足以进一步测试像自定义字段或方法的异常对象,或在抛出异常的方法后执行额外的断言。
为了解决这个问题,JUnit 5 提供了一个新的断言,expectthrows,不仅可以检查一个特定方法抛出的预期异常,同时将异常对象作为一个结果返回,允许进一步测试。
@Test void exceptionTesting() { Throwable exception = expectThrows(IllegalArgumentException.class, () -> { throw new IllegalArgumentException("a message"); } ); assertEquals("a message", exception.getMessage()); }
来自 JUnit 5 用户指南的示例代码。
扩展性也是新版本关注的一个方面。JUnit 4 主要的扩展机制是 @RunWith。但是,@RunWith 在任何给定的测试类上只能使用一次,这意味着开发人员不能同时使用,例如, Parameterized 在同样的测试中应用不同的数据以及 MockitoJUnitRunner 自动设置 mocks。在 JUnit 5 @RunWith 已经被 @ExtendWith 取代,这是一个新的扩展机制,支持多个实例被使用。
为了让开发人员逐步升级到新版本,JUnit 5 所有的类已经迁移到新的包,许多注解已经重命名。此外,JUnit Lambda 团队为 JUnit 4 创建了一个 JUnit 5 Runner ,允许使用 JUnit 5 所有特性的同时仍然以 JUnit 4 为主要的测试框架。这使得 JUnit 4 和 JUnit 5 有可能在同一个项目中同时使用,使过渡变得更容易。
被关注的问题还有,通过语义化的版本号命名(semantic versioning)和加注解的 API,使得未来的变更更加方便,甚至包括那些向后不兼容的变更。从 JUnit 5 开始,测试框架中每一个公共类和接口都将标有下列值之一:
- Internal:不适合在框架之外使用,随时可能被删除,并且可能不会事先通知。
- Deprecated:不应使用的,在下一个小版本可能会去掉。
- Experimental:用来收集对新概念的反馈,它可能被改进,也可能在没有事先通知的情况下被删除。
- Maintained:从当前版本到至少下一个小版本没有向后不兼容的更改,如果计划删除,它首先会被修改为 Deprecated。
- Stable:在目前的主要版本没有向后不兼容的更改。
在上一个主要版本发布十年之后,JUnit 似乎赶上了时代的步伐。虽然与构建工具和集成开发环境的整合还需要一些工作,但是为 Maven 和 Gradle 提供的插件看起来是相当先进的,这似乎表明,在可预见的未来 JUnit 将继续是主要的 Java 测试框架。
查看英文原文: JUnit 5 Alpha Simplifies Unit Testing
感谢丁涛对本文的审校。
给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ , @丁晓昀),微信(微信号: InfoQChina )关注我们,并与我们的编辑和其他读者朋友交流(欢迎加入 InfoQ 读者交流群(已满),InfoQ 读者交流群(#2))。
评论