Java测试中主要使用JUnit库进行测试,但是JUnit的断言相关API可读性不高,因此需要一款更好的断言库进行断言。AssertJ就是一款流式的断言库,大大提高了代码的可读性。
Spring Boot官方发行了一个Starter:spring-boot-starter-test,其中自带很多测试库,如JUnit,Mockito等,AssertJ也在这个Starter中。spring-boot-starter-test。
Gradle
testImplementation("org.springframework.boot:spring-boot-starter-test:2.7.3")
Maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.7.3</version>
<scope>test</scope>
</dependency>
testImplementation("org.assertj:assertj-core:3.23.1")
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<!-- use 2.9.1 for Java 7 projects -->
<version>3.23.1</version>
<scope>test</scope>
</dependency>
AssertJ可以通过以下两种方式引入
使用import static导入测试方法
import static org.assertj.core.api.Assertions.*;
// 或者使用下面的方法导入
// 最常用的测试方法
import static org.assertj.core.api.Assertions.assertThat;
// 列表、字典、迭代器/Array
import static org.assertj.core.api.Assertions.atIndex;
import static org.assertj.core.api.Assertions.entry;
import static org.assertj.core.api.Assertions.filter;
// 文件
import static org.assertj.core.api.Assertions.contentOf;
// 其他不常用测试方法略
// 后续在测试方法中使用
assertThat("This is a string")
.isNotNull()
.startsWith("This")
.contains("a")
.endsWith("string");
实现WithAssertions接口
import org.assertj.core.api.WithAssertions;
public class ExampleTest implements WithAssertions {
@Test
public void testAString() {
assertThat("This is a string")
.isNotNull()
.startsWith("This")
.contains("a")
.endsWith("string");
}
}
下面列举的assert方法在大部分情况下都可以使用。
这两类方法可以设置测试的信息以及失败后的提示信息.。要注意的是,这两个方法需要放在对应的测试前进行调用,否则不会生效!
as/describedAs
as(String description, Object ... args); // 对后续调用的测试进行描述
as(Supplier<String> descriptionSupplier); // 懒加载后续测试的描述,如果测试成功,那么Supplier不会被调用
describedAs(String description, Object ... args); // as方法的别名,因为'as'在Groovy中是关键字
overridingErrorMessage/withFailMessage
overridingErrorMessage(String newErrorMessage, Object... args); // 设置错误信息
overridingErrorMessage(Supplier<String> supplier); // 懒加载错误信息,如果测试成功,那么Supplier不会被调用
withFailMessage(String newErrorMessage, Object... args); // 设置错误信息
withFailMessage(Supplier<String> supplier); // 懒加载错误信息,效果同上
用于判断一个对象是否是null,或者判断两个对象是否相等。
isEqualTo/isNotEqualTo
isEqualTo(Object expected); // 判断两个对象是否相等,使用equals方法
isNotEqualTo(Object other); // 与上面结果相反,使用equals方法
isNull/isNotNull
void isNull(); // 如果对象是null,那么测试通过且后续无法进行任何测试
isNotNull(); // 如果对象不是null,那么测试通过,后续可以继续进行测试
isSameAs/isNotSameAs(因为使用’==’进行判断,因此需要谨慎使用!)
isSameAs(Object expected); // 判断对象是否相等,使用'=='进行判断
isNotSameAs(Object other); // 与上面结果相反,使用'=='进行判断
用于判断一个对象是否属于一个(或多个)类型,以及判断两个对象是否是同一类型。
isInstanceOf/isNotInstanceOf
isInstanceOf(Class<?> type); // 判断对象是否是type类型(相当于instanceof)
isNotInstanceOf(Class<?> type); // 与isInstanceOf相反
isInstanceOfAny/isNotInstanceOfAny/isOfAnyClassIn/isNotOfAnyClassIn
isInstanceOfAny(Class<?>... types); // 如果对象类型是types中的任意一个,那么测试通过
isNotInstanceOfAny(Class<?>... types); // 与isInstanceOfAny相反
isOfAnyClassIn(Class<?>... types); // 同isInstanceOfAny
isNotOfAnyClassIn(Class<?>... types); // 同isNotInstanceOfAny
isInstanceOfSatifying
isInstanceOfSatisfying(Class<T> type, Consumer<T> requirements); // 首先判断是否满足类型,之后判断是否满足后续的要求,举例如下
Consumer<String> requirements = string -> {
assertThat(string).contains("substring").startsWith("beginning");
};
assertThat("beginning substring").isInstanceOfSatisfying(String.class, requirements);
isExactlyInstanceOf/isNotExactlyInstanceOf
isExactlyInstanceOf(Class<?> type); // 判断object.class是否等于type
isNotExactlyInstanceOf(Class<?> type); // 与上面的结果相反,可能考虑子类的情况,举例如下
assertThat(new ArrayList<String>()).isExactlyInstanceOf(ArrayList.class); // 成功
assertThat(new ArrayList<String>()).isExactlyInstanceOf(List.class); // 失败
hasSameClassAs/doesNotHaveSameClassAs
hasSameClassAs(Object other); // 如果两个对象是相同类型,那么测试通过
doesNotHaveSameClassAs(Object other); // 与上面结果相反,举例如下
assertThat(new ArrayList<String>()).hasSameClassAs(new ArrayList<Integer>()); // 通过
assertThat(1).hasSameClassAs("abc"); // 不通过
判断对象调用toString/hashCode方法后的结果
hasToString/doesNotHaveToString
hasToString(String expectedToString); // 如果对象在调用toString后的值与expectedToString一致,那么测试通过
doesNotHaveToString(String otherToString); // 与上面结果相反
// 以下两种方法是等效的
assertThat(object.toString()).isEqualTo(expected);
assertThat(object).hasToString(expected);
hasSameHashCodeAs/doesNotHaveSameHashCodeAs
hasSameHashCodeAs(Object other); // 如果两个对象的Hash code一致,那么测试通过
doesNotHaveSameHashCodeAs(Object other); // 与上面结果相反
// 虽然这两个方法和上面的toString测试方法一样有等效方式,但是写起来比较麻烦,故在此省略
这个方法有两个重载,用于在AssertJ的API不方便进行判断是使用,需要传入一个Predicate类型的lambda表达式进行判断。
matches(Predicate<? super ACTUAL> predicate); // 传入Predicate进行测试
matches(Predicate<? super ACTUAL> predicate, String predicateDescription); // 传入Predicate及其描述信息
下面的方法用于进行简单的类型转换
asString
asString(); // 调用对象的toString方法,对后续toString的结果继续测试,举例如下
Object stringAsObject = "hello world";
assertThat(stringAsObject).asString().contains("hello");
asList
asList(); // 判断对象是不是List类型的对象,后续可以执行对List的测试方法,举例如下
Object sortedListAsObject = Arrays.asList(1, 2, 3);
assertThat(sortedListAsObject).asList().isSorted();
asInstanceOf
// 因为代码有些复杂,因此贴出完整的类型定义
public <ASSERT extends AbstractAssert<?,?>> ASSERT asInstanceOf(InstanceOfAssertFactory<?,ASSERT> instanceOfAssertFactory);
// 使用InstanceOfAssertFactory的对象来将对象转换成其他类型的对象(主要是Type Narrowing),以便对类型转换后的对象执行后续测试
// 举例如下
Object string = "abc";
assertThat(string).asInstanceOf(InstanceOfAssertFactories.STRING).startsWith("ab");
Object integer = 1;
assertThat(integer).asInstanceOf(InstanceOfAssertFactories.INTEGER).isNotZero();
// 如果类型转换失败,测试会失败,举例如下
assertThat("abc").asInstanceOf(InstanceOfAssertFactories.INTEGER);