文章目录
使用AssertJ让单元测试和TDD更加简单
前言
在编写单元测试时,一个重要的工作就是编写断言(Assertion),而JUnit自带的断言机制和Hamcrest的assertThat
都不那么好用。
利用AssertJ,可以让单元测试更加简单,让TDD过程更加顺畅。
AssertJ的优点:
- 通用的
assertThat
“流式断言”,让编写断言更加简单快捷。 - API丰富,对各种类型的断言都非常友好。
环境
本文的测试环境:
- JUnit4
- assertj-core
- Maven
- Java8
添加assertJ的Maven依赖:
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.17.0</version>
<scope>test</scope>
</dependency>
在测试类中引入AssertJ:
import static org.assertj.core.api.Assertions.*;
断言类型
常用的断言类型
常用的断言类型包括:
isSameAs
: 同一个对象。isEuqalsTo
: 值相等。isCloseTo
: 值相近。isTrue
:为真,isFalse
为假。containsExactly
:包含全部元素,顺序也保持一致。containsOnly
:包含全部元素,顺序不需要保持一致。contains
:包含给定的元素。hasSize
:长度或大小或元素个数为N个。isEmpty
: 是否为空。isNull
:是否为null。isInstanceOf
:是否为指定类型。
断言的辅助方法
断言的辅助方法:
-
extracting
: 提取,根据类名或方法引用或字段名反射调用,或根据lambda表达式调用。 -
mathes
: 匹配,根据lambda表达式调用。 -
atIndex
: 获取指定位置/索引的元素。 -
offset
: 偏移量。 -
withPercentage
:百分比。 -
tuple
:将一组属性的值包装成元组。 -
entry
:将键值对({K,V})包装成Map.Entry。
AssertJ例子
官网:
- https://github.com/assertj/assertj-core
- https://github.com/joel-costigliola/assertj-examples/tree/main/assertions-examples/src/test/java/org/assertj/examples
基本类型
参见:
说明:
- 对可以精确匹配的值(比如字符串、整数),用
isEqualTo()
来比较,对不能精确匹配的值(比如浮点数),用isCloseTo()
比较。 - 对布尔值,用
isTrue()
或isFalse()
来比较。
@Test
public void test_value_equals() {
String hello = "hello".toUpperCase();
assertThat(hello).isEqualTo("HELLO");
int secondsOfDay = 24 * 60 * 60;
assertThat(secondsOfDay).isEqualTo(86400);
}
@Test
public void test_value_close() {
double result = 0.1 + 0.1 + 0.1; // 0.30000000000000004
assertThat(result).isCloseTo(0.3, offset(0.0001)); // 误差值
assertThat(result).isCloseTo(0.3, withPercentage(0.01)); // 误差百分比
}
@Test
public void test_boolean() {
boolean flag = "Kubernetes".length() > 8;
assertThat(flag).isTrue();
boolean flag2 = "Docker".length() > 8;
assertThat(flag2).isFalse();
}
单个对象
参见:
说明:
- 判断是否为同一个对象用
isSameAs()
。 - 如果重写了euqals和hashcode方法,也可以用
isEqualTo
来判断对象是否相同。 - 如果只是判断对象的值是否相等,则可以用
extracting
提取后再判断,或用matches
来用lambda表达式判断。 - 判断是否为null用
isNull()
或isNotNull()
。
@Test
public void test_object_null_or_not_null() {
Person p1 = new Person("William", 34);
assertThat(p1).isNotNull();
Person p2 = null;
assertThat(p2).isNull();
}
@Test
public void test_object_same_as_other() {
Person p1 = new Person("William", 34);
Person p2 = p1;
assertThat(p1).isSameAs(p2);
Person p3 = new Person("John", 35);
assertThat(p1).isNotSameAs(p3);
}
@Test
public void test_object_equals() {
Person p1 = new Person("William", 34);
Person p2 = new Person("William", 34);
assertThat(p1).isNotSameAs(p2);
assertThat(p1).isNotEqualTo(p2); // 如果用isEqualTo判断,则必须要重写equals方法
// extracting method reference
assertThat(p1).extracting(Person::getName, Person::getAge).containsExactly("William", 34);
assertThat(p1).extracting(Person::getName, Person::getAge).containsExactly(p2