Google Truth:让 Java 测试断言读起来更像一句话
文章目录
- Google Truth:让 Java 测试断言读起来更像一句话
- 1、 这玩意儿是干嘛的
- 2、 为什么要用它
- 3、 怎么用
- 4、 适合哪些场景
Google Truth:让 Java 测试断言读起来更像一句话
Truth 在 GitHub 上已经累积 2,786 Star,是 Google Guava 团队操刀维护的断言库。
它就做一件事,把测试里的断言写得更像人话,让失败信息一眼看明白哪里错了。
1、 这玩意儿是干嘛的
写 Java 测试的人对 JUnit 自带的assertEquals不陌生。一行assertEquals(expected, actual)写下来,断言干了什么一目了然,可一旦失败,堆栈里甩出来的信息只有 expected 和 actual 两个值,要弄清它们各自的来源就要回到测试代码翻上下文。
Truth 把断言拆成主语和谓语的结构。assertThat(actual).isEqualTo(expected)读起来就是一句话,assertThat(list).hasSize(5)直接说出意图。失败信息也跟着变样,会告诉你「value at index 3 was expected to be X but was Y」,定位点的颗粒比 JUnit 原生断言细得多。
它原生支持一长串 JDK 和 Guava 类型,集合、Map、Optional、Multimap、Table 这些都能直接断言,不用再写assertThat(map.size()).isEqualTo(5)这种绕一圈的写法。
2、 为什么要用它
写过测试断言的人多半遇到过这种场景:一段assertEquals(expected, actual)跑挂,message 里只给你两个对象 toString 后的值,你要自己对照哪个是哪个。复杂集合一上来,失败信息就是一大坨字串,肉眼比对两分钟起步。
Truth 处理这件事有自己的套路。对集合断言,它会在失败信息里给出索引、给出期望值、给出实际值,必要时告诉你哪些元素多出来、哪些少了。assertThat(multimap).hasSize(3)失败时,信息里会带上 multimap 当前内容,不用你再单独打 log 把对象 dump 一遍。
可读性之外,可扩展性也是它一条主线。自定义类型实现Subject接口就能挂进来,逻辑跟内置类型一脉相承。做内部库的人拿这个机制包一层,团队 DSL 就算立起来了。
3、 怎么用
Maven 工程加一行依赖:
<dependency><groupId>com.google.truth</groupId><artifactId>truth</artifactId><version>1.4.4</version></dependency>Gradle 同理:
testImplementation 'com.google.truth:truth:1.4.4'接着在测试里替换原来的断言:
importstaticcom.google.common.truth.Truth.assertThat;assertThat(actualResult).isEqualTo(expectedResult);assertThat(userList).hasSize(3);assertThat(userList).containsExactly(userA,userB,userC);assertThat(optionalValue).isPresent();assertThat(thrown).hasMessageThat().contains("not found");API 风格跟 AssertJ 走的是同一条路,二者在 API 设计、可读性、扩展机制上的取舍接近。已有项目用 AssertJ 不必硬迁,新项目想跟 Guava 套件贴得近一点,Truth 的集成成本会比 AssertJ 低。
4、 适合哪些场景
- Java 项目里写测试断言量很大、失败信息定位成本高的工程团队
- 用 Guava 类型比较多的代码库,原生断言能省一层适配
- 需要给内部领域对象写一套断言 DSL,希望挂在成熟框架上的场景
Google 自己的代码库里大头测试都跑在 Truth 上,Guava 团队亲自维护,节奏稳定。文档站点 truth.dev 上放了对比、扩展指南和已知类型清单,决定要不要上之前翻一遍就够判断。
ava 团队亲自维护,节奏稳定。文档站点 truth.dev 上放了对比、扩展指南和已知类型清单,决定要不要上之前翻一遍就够判断。
