AssertJ详解

AssertJ

1、概述

AssertJ 是一个 Java 库,它提供了丰富的断言集和真正有用的错误消息,提高了测试代码的可读性。

AssertJ由几个模块组成:

  • 核心模块:为 JDK 类型(String、Iterable、Stream、Path、File、Map,…)提供断言
  • Guava模块:为 Guava 类型提供断言(Multimap、Optional,…​)
  • Joda Time模块:为Joda Time 类型(DateTime、LocalDateTime)提供断言
  • Neo4J模块:为 Neo4J 类型(路径、节点、关系……)提供断言
  • Swing模块:为Swing 用户界面的功能测试提供了简单直观的 API

不同的 AssertJ 主要版本取决于不同的 Java 版本:

  • AssertJ 3.x 需要 Java 8 或更高版本
  • AssertJ 2.x 需要 Java 7 或更高版本
  • AssertJ 1.x 需要 Java 6 或更高版本

2、AssertJ 核心

AssertJ 核心提供 JDK 标准类型的断言,可以与 JUnit、TestNG 或任何其他测试框架一起使用。

<dependency>
    <groupId>org.assertj</groupId>
    <artifactId>assertj-core</artifactId>
    <version>3.4.1</version>
    <scope>test</scope>
</dependency>

2.1、简单示例

import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static org.assertj.core.api.Assertions.*;

public class DemoTest {


    @Test
    public void test() {
        Person p1 = new Person("tom", 18);
        Person p2 = new Person("jerry", 22);

        //基础断言
        assertThat(p1.getName()).isEqualTo("tom");
        assertThat(p1).isNotEqualTo(p2);

        //字符串断言
        assertThat("hello")
                .startsWith("he")
                .endsWith("lo")
                .isEqualToIgnoringCase("HELLO");

        //集合断言
        Set<String> set = new HashSet<>();
        set.add("a");
        set.add("b");
        set.add("c");
        assertThat(set).hasSize(3)
                .contains("b", "c")
                .doesNotContain("z");

        //断言描述
        assertThat(p1.getAge())
                .as("check %d's age", p1.getAge())
                .isEqualTo(18);

        //异常断言,标准风格
        assertThatThrownBy(() -> {
            throw new Exception("boom!");
        }).hasMessage("boom!");

        //异常断言,BDD风格
        Throwable thrown = catchThrowable(() -> {
            throw new Exception("boom!");
        });
        assertThat(thrown).hasMessageContaining("boom");

        //提取多个值为元组并断言
        List<Person> list = new ArrayList<>();
        list.add(p1);
        list.add(p2);
        assertThat(list).extracting("name", "age")
                .contains(tuple("tom", 18), tuple("jerry", 22));

        //断言之前过滤集合
        assertThat(list).filteredOn(p -> p.getAge() > 18)
                .containsOnly(p2);

        //过滤和提取组合并断言
        assertThat(list).filteredOn(p -> p.getAge() > 18)
                .containsOnly(p2)
                .extracting("name", "age")
                .contains(tuple("jerry", 22));
    }

    class Person {
        String name;
        Integer age;

        public Person(String name, Integer age) {
            this.name = name;
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Integer getAge() {
            return age;
        }

        public void setAge(Integer age) {
            this.age = age;
        }
    }
}

2.2、断言入口

1)、Assertions

org.assertj.core.api.Assertions是AssertJ断言所需的唯一类,它提供了所需的所有方法。

一个静态导入即可:

import static org.assertj.core.api.Assertions.*;

也可以细分后按需导入:

import static org.assertj.core.api.Assertions.assertThat;  // main one
import static org.assertj.core.api.Assertions.atIndex; // for List assertions
import static org.assertj.core.api.Assertions.entry;  // for Map assertions
import static org.assertj.core.api.Assertions.tuple; // when extracting several properties at once
import static org.assertj.core.api.Assertions.fail; // use when writing exception tests
import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown; // idem
import static org.assertj.core.api.Assertions.filter; // for Iterable/Array assertions
import static org.assertj.core.api.Assertions.offset; // for floating number assertions
import static org.assertj.core.api.Assertions.anyOf; // use with Condition
import static org.assertj.core.api.Assertions.contentOf; // use with File assertions
2)、WithAssertions

org.assertj.core.api.WithAssertions接口是断言的另一个入口,只需实现该类即可。

import org.assertj.core.api.WithAssertions;
import org.junit.jupiter.api.Test;


public class WithAssertionsExamples implements WithAssertions {
    
    @Test
    public void test() {
        //不需要静态导入,assertThat是来自于WithAssertions的方法
        assertThat("hello").isEqualTo("hello");
        assertThat(1).isInstanceOf(Number.class);
    }
    
}
3)、BDDAssertions

org.assertj.core.api.BDDAssertions.then是另一个断言入口。

import org.junit.jupiter.api.Test;

import static org.assertj.core.api.BDDAssertions.then;

public class BDDAssertionsExamples {

    @Test
    public void test() {
        //方法来自静态导入的BDDAssertions.then()
        then("hello").isEqualTo("hello");
        then(1).isInstanceOf(Number.class);
    }
}

2.3、断言支持的类型

常见类型:

  • BigDecimal
  • BigInteger
  • CharSequence
  • Class
  • Date
  • File
  • Future / CompletableFuture
  • InputStream
  • Iterable (including any kind of Collection)
  • Iterator
  • List
  • Map
  • Object
  • Object[] and Object[][]
  • Optional / OptionalInt / OptionalLong / OptionalDouble
  • Path
  • Predicate
  • Stream
  • String
  • Throwable / Exception

原始类型:

  • 原始类型及其包装器
    • short / Short
    • int / Integer
    • long / Long
    • byte / Byte
    • char / Character
    • float / Float
    • double / Double
  • 原始类型数组
    • short[]
    • int[]
    • long[]
    • byte[]
    • char[]
    • float[]
    • double[]
  • 原始类型二维数组
    • short[][]
    • int[][]
    • long[][]
    • byte[][]
    • char[][]
    • float[][]
    • double[][]

Java8时间类型:

  • Instant
  • LocalDate
  • LocalDateTime
  • LocalTime
  • OffsetDateTime
  • OffsetTime
  • ZonedDateTime
  • Period

原子类型:

  • 原子基本类型
    • AtomicInteger
    • AtomicLong
    • AtomicBoolean
  • 原子数组类型
    • AtomicIntegerArray
    • AtomicLongArray
  • 原子引用类型
    • AtomicMarkableReference
    • AtomicStampedReferenceAssert
  • 原子更新器类型
    • AtomicIntegerFieldUpdater
    • AtomicLongFieldUpdater
    • AtomicReferenceFieldUpdater
  • 加法器类型
    • LongAdder

2.4、断言描述

可以使用as方法为断言添加描述。

@Test
public void asTest() {
    //注意,要在断言之前调用as方法
    assertThat("hello")
            .as("描述")
            .isEqualTo("hello");

    assertThat(1)
            .as("check %s num", 1)
            .isGreaterThan(18);
}
java.lang.AssertionError: [check 1 num] 
Expecting:
 <1>
to be greater than:
 <18> 

AssertJ 可以打印每个断言描述(当设置时),为此调用Assertions.setPrintAssertionsDescription(true);

2.5、错误消息覆盖

可以使用如下两个方法覆盖默认的错误消息:

  • overridingErrorMessage()
  • withFailMessage()
@Test
public void errMessageTest() {
    assertThat(1)
            .withFailMessage("check %s num", 1)
            .isGreaterThan(18);

    assertThat(1)
            .overridingErrorMessage("check %s num", 1)
            .isGreaterThan(18);
}

如果构建错误消息的成本很高,请使用重载方法,采用 Supplier<String>而不是String,只有在断言失败时才会构建消息。

@Test
public void errMessageTest2() {
    assertThat(1)
            .withFailMessage(() -> "check num")
            .isGreaterThan(18);

    assertThat(1)
            .overridingErrorMessage(() -> "check num")
            .isGreaterThan(18);
}

2.6、配置AssertJ

有两种配置AssertJ的不同方法:

  • 单独设置配置属性
  • 全局设置配置属性

为了有效,必须在执行测试之前应用配置更改,这取决于测试的范围,这意味着不同的事情:

  • 对于单个测试:更改测试中的配置并在@AfterEach方法中恢复它(JUnit 5)
  • 对于类中的所有测试:更改方法中的配置@BeforeAll并恢复方法中的更改@AfterAll(JUnit 5)
  • 要在任何测试之前更改配置可以使用以下选项
    • 编写 JUnit 5 扩展实现BeforeAllCallback.
    • 注册您自己的Configuration子类并让 AssertJ自动发现它。
1)、配置单个属性
//是否允许使用私有字段进行比较
Assertions.setAllowComparingPrivateFields(true);
//是否允许提取私有字段
Assertions.setAllowExtractingPrivateFields(false);
//设置提取器是否考虑裸命名的属性方法
Assertions.setExtractBareNamePropertyMethods(false);
//是否使用宽松的日期解析
Assertions.setLenientDateParsing(true);
//为可迭代对象、数组和map设置在错误消息中显示的最大元素数
Assertions.setMaxElementsForPrinting(100);
//设置单行描述的最大长度
Assertions.setMaxLengthForSingleLineDescription(250);
//设置是否从断言错误堆栈跟踪中删除与 AssertJ 相关的元素
Assertions.setRemoveAssertJRelatedElementsFromStackTrace(true);
//注册一个Representation来控制 AssertJ 格式化断言错误消息中显示的不同类型的方式
//默认为StandardRepresentation
Assertions.useRepresentation(new StandardRepresentation());
//注册一些 AssertJ 将在日期断言中使用的自定义格式
Assertions.registerCustomDateFormat(new SimpleDateFormat());
//启用/禁用向控制台打印断言描述
Assertions.setPrintAssertionsDescription(true);
2)、Congifuration

从 3.13.0 开始,AssertJ 公开了一个org.assertj.core.configuration.Configuration对象,提供对所有 AssertJ 全局可配置属性的访问。

//创建配置对象
Configuration configuration = new Configuration();
//设置属性
configuration.setBareNamePropertyExtraction(false);
configuration.setComparingPrivateFields(false);
configuration.setExtractingPrivateFields(false);
configuration.setLenientDateParsing(true);
configuration.setMaxElementsForPrinting(1001);
configuration.setMaxLengthForSingleLineDescription(81);
configuration.setRemoveAssertJRelatedElementsFromStackTrace(false);
//应用,不要忘记调用apply方法
configuration.applyAndDisplay();

2.7、常用断言

常用断言位于AbstractAssert类中:

  • describedAs:设置之后将调用的断言的描述
  • isEqualTo:验证实际值是否等于给定值,即使用equals比较
  • isNotEqualTo:验证实际值是否不等于给定值,即使用equals比较
  • isNull:验证是否为Null
  • isNotNull:验证是否不为Null
  • isSameAs:验证实际值是否与给定值相同,即使用==比较
  • isNotSameAs:验证实际值是否与给定值不相同,即使用==比较
  • isIn:验证实际值是否存在于给定的值数组/集合中
  • isNotIn:验证实际值是否不存在于给定的值数组/集合中
  • is/has/satisfies:验证实际值是否满足给定条件,has方法别名
  • isNot/doesNotHave:验证实际值是否不满足给定条件。这个方法是doesNotHave的别名
  • isInstanceOf:验证实际值是否是给定类型的实例
  • isInstanceOfSatisfying:验证实际值是一个给定类型的实例,满足以Consumer表示的给定需求
  • isInstanceOfAny:验证实际值是否为任何给定类型的实例
  • isNotInstanceOf:验证实际值是否不是给定类型的实例
  • isNotInstanceOfAny:验证实际值是否不为任何给定类型的实例
  • hasSameClassAs:验证实际值是否与给定对象具有相同的类
  • hasToString:验证toString方法的返回值是否一致
  • doesNotHaveSameClassAs:验证实际值是否与给定对象不具有相同的类
  • isExactlyInstanceOf:验证实际值是否恰好是给定类型的实例
  • isNotExactlyInstanceOf:验证实际值是否恰好不是给定类型的实例
  • isOfAnyClassIn:验证实际值类型是否在给定类型中
  • isNotOfAnyClassIn:验证实际值类型是否不在给定类型中
  • asList:验证实际值是List的一个实例,并返回一个列表断言,以允许在此调用中链接特定于列表的断言
  • asString:为实际值的toString()返回一个String断言,以允许在此调用中链接特定于String的断言
  • overridingErrorMessage:覆盖错误信息
  • withFailMessage:覆盖错误信息
  • usingComparator:使用给定的自定义比较器
  • usingDefaultComparator:使用默认比较器
  • matches:验证实际对象是否与给定谓词匹配
  • satisfiesAnyOf:验证所测试的实际对象是否满足以Consumer表示的给定断言组中的至少一个
//设置断言描述
assertThat(1).describedAs("描述").isLessThan(2);

//equals比较
assertThat(Integer.valueOf(1)).isEqualTo(1);
assertThat(1).isNotEqualTo(2);

//是否为Null
String str = null;
assertThat(str).isNull();
assertThat(new Object()).isNotNull();

// ==比较引用
assertThat(Integer.valueOf(1)).isSameAs(Integer.valueOf(1));
assertThat(Integer.valueOf(128)).isNotSameAs(Integer.valueOf(128));

// 是否存在
List<Integer> list = Arrays.asList(4, 5, 6);
assertThat(1).isIn(1, 2, 3);
assertThat(4).isIn(list);
assertThat(9).isNotIn(1, 2, 3);
assertThat(9).isNotIn(list);

//条件断言
Condition<String> condition = new Condition<String>(s -> s.length() < 6, "a %s word", "short");
assertThat("hello").is(condition);
assertThat("hello").has(condition);
assertThat("hello").satisfies(condition);

//类型判断
assertThat(Integer.valueOf(1)).isInstanceOf(Number.class);
assertThat(Integer.valueOf(1)).isInstanceOfAny(Number.class, Integer.class);
assertThat(Integer.valueOf(1)).hasSameClassAs(Integer.valueOf(2));

2.8、对象断言

对象断言位于AbstractObjectAssert类中:

  • as:添加描述
  • hasNoNullFieldsOrProperties:断言实际对象没有空字段或属性(将继承的字段或属性考虑在内)
  • hasAllNullFieldsOrProperties:断言实际对象只有空字段或属性
  • hasNoNullFieldsOrPropertiesExcept:断言实际对象没有空字段或属性,除了给定的(继承的也要考虑在内)
  • hasAllNullFieldsOrPropertiesExcept:断言实际对象只有空字段或属性,除了给定的(继承的也要考虑在内)
  • usingComparatorForFields:允许设置一个特定的比较器来比较具有给定名称的属性或字段。一个典型的用法是比较给定精度的double/float字段
  • usingComparatorForType:允许设置一个特定的比较器,将属性或字段与给定类型进行比较。典型的用法是在给定精度下比较数值类型的字段
  • hasFieldOrProperty:断言实际对象是否具有指定的字段或属性
  • hasFieldOrPropertyWithValue:断言实际对象具有给定值的指定字段或属性
  • extracting:从被测对象中提取给定字段/属性的值到一个列表中,这个新列表成为被测对象
  • returns:验证被测对象从给定的返回给定的期望值,一个典型的用法是传递一个方法引用来断言对象的属性
Book b1 = new Book();
//只有空字段
assertThat(b1).hasAllNullFieldsOrProperties();
b1.setName("三国演义");
assertThat(b1).hasAllNullFieldsOrPropertiesExcept("name");

//没有空字段
assertThat(b1).hasNoNullFieldsOrPropertiesExcept("author", "price");
b1.setAuthor("罗贯中");
b1.setPrice(22.22);
assertThat(b1).hasNoNullFieldsOrProperties();

//判断是否具有指定字段
assertThat(b1).hasFieldOrProperty("name");
assertThat(b1).hasFieldOrPropertyWithValue("name", "三国演义");

//提取值
assertThat(b1).extracting("name", "author")
        .contains("三国演义", "罗贯中");

2.9、字符串断言

字符串断言位于AbstractCharSequenceAssert类中:

  • isNullOrEmpty:验证字符串为Null或空
  • isEmpty:验证字符串为空
  • isNotEmpty:验证字符串非空
  • isBlank:验证字符串为空或由一个或多个空格组成
  • isNotBlank:验证字符串不为空或不由一个或多个空格组成
  • containsWhitespaces:验证字符串包含一个或多个空格
  • containsOnlyWhitespaces:验证字符串只包含空格
  • doesNotContainAnyWhitespaces:验证字符串为Null、空或不包含任何空格
  • doesNotContainOnlyWhitespaces:验证字符串至少有一个非空格字符
  • hasSize:验证字符串具有指定长度
  • hasSizeLessThan:验证字符串小于指定长度
  • hasSizeLessThanOrEqualTo:验证字符串小于等于指定长度
  • hasSizeGreaterThan:验证字符串大于指定长度
  • hasSizeGreaterThanOrEqualTo:验证字符串大于等于指定长度
  • hasSizeBetween:验证字符串具有给定边界(包含)之间的长度
  • hasLineCount:验证字符串具有指定的行数
  • hasSameSizeAs:验证实际字符串和给定字符串长度相同
  • isEqualToIgnoringCase:忽略大小写比较相等
  • isNotEqualToIgnoringCase:忽略大小写比较不相等
  • containsOnlyDigits:验证字符串只包含数字
  • containsOnlyOnce:验证字符串只包含一次给定序列
  • contains:验证字符串包含指定子串
  • containsSequence:验证字符串以指定顺序包含子串
  • containsIgnoringCase:忽略大小写包含
  • doesNotContain:验证字符串不包含子串
  • doesNotContainIgnoringCase:验证字符串不包含子串(忽略大小写)
  • doesNotContainPattern:验证字符串不包含给定的正则表达式
  • startsWith:以…开头
  • doesNotStartWith:不以…开头
  • endsWith:以…结尾
  • doesNotEndWith:不以…结尾
  • matches:验证字符串与给定的正则表达式匹配
  • doesNotMatch:验证字符串不与给定的正则表达式匹配
  • isXmlEqualToContentOf:验证实际的字符串是否等于给定文件的内容
  • isEqualToIgnoringWhitespace:验证实际的字符串等于给定的,忽略空格差异
  • isNotEqualToIgnoringWhitespace:验证实际的字符串不等于给定的,忽略空格差异
  • isEqualToNormalizingWhitespace:验证实际的字符串等于给定的,在两个字符串的空格被标准化之后
  • isNotEqualToNormalizingWhitespace:验证实际的字符串不等于给定的,在两个字符串的空格被标准化之后
  • isEqualToNormalizingPunctuationAndWhitespace:验证实际的字符串等于给定的,在两个字符串的标点符号被规范化之后
  • isSubstringOf:验证实际的字符串是给定的子字符串(与contains相反的断言)
  • containsPattern:验证实际的字符串是否包含给定的正则表达式
  • isEqualToNormalizingNewlines:验证实际的字符串在规范化新行字符后等于另一个字符串
  • isEqualToIgnoringNewLines:验证在两个字符串新行(\n, \r\n)被删除后,实际的字符串等于给定的字符串
  • isLowerCase:验证是否全部为小写
  • isUpperCase:验证是否全部为大写
//断言null、空、空格
assertThat("").isNullOrEmpty();
assertThat("").isEmpty();
assertThat("a").isNotEmpty();
assertThat("  ").isBlank();
assertThat("a").isNotBlank();

//包含空
assertThat("a b").containsWhitespaces();
assertThat("  ").containsOnlyWhitespaces();
assertThat("ab").doesNotContainAnyWhitespaces();
assertThat("a b c").doesNotContainOnlyWhitespaces();

//字符串长度
assertThat("hello").hasSize(5);
assertThat("hello").hasSizeLessThan(6);
assertThat("hello").hasSizeLessThanOrEqualTo(5);
assertThat("hello").hasSizeGreaterThan(4);
assertThat("hello").hasSizeLessThanOrEqualTo(5);
assertThat("hello").hasSizeBetween(4, 6);
assertThat("hello").hasSameSizeAs("world");

//字符串行数
assertThat("hello\nworld").hasLineCount(2);

//字符串相等
assertThat("hello").isEqualTo("hello");
assertThat("hello").isEqualToIgnoringCase("Hello");
assertThat("hello").isNotEqualToIgnoringCase("Hallo");
//忽略空格
assertThat("a b c").isEqualToIgnoringWhitespace("abc");
assertThat("a b c").isNotEqualToIgnoringWhitespace("aba");

//只包含数字
assertThat("1234").containsOnlyDigits();

//包含子串
assertThat("hello world").containsOnlyOnce("hel");
assertThat("hello world").contains("wor", "hel");
assertThat("hello world").containsSequence("hel", "lo");
assertThat("hello world").containsIgnoringCase("HEL");
assertThat("hello world").doesNotContain("bb");
assertThat("hello world").doesNotContainIgnoringCase("BB");
assertThat("hello world").doesNotContainPattern(Pattern.compile("^a.*"));

//开头结尾
assertThat("hello").startsWith("he");
assertThat("hello").doesNotStartWith("ha");
assertThat("hello").endsWith("lo");
assertThat("hello").doesNotEndWith("la");

//正则匹配
assertThat("hello").matches(Pattern.compile("^he.*"));
assertThat("hello").doesNotMatch(Pattern.compile("^ha.*"));

//子串
assertThat("abc").isSubstringOf("abcdef");

//大小写
assertThat("hello").isLowerCase();
assertThat("HELLO").isUpperCase();

2.10、可迭代断言

可迭代对象的断言都位于AbstractIterableAssert类中:

  • isNullOrEmpty:Null或空
  • isEmpty:验证为空
  • isNotEmpty:非空
  • hasSize:等于指定容量
  • hasSizeGreaterThan:大于指定容量
  • hasSizeGreaterThanOrEqualTo:大于等于指定容量
  • hasSizeLessThan:小于指定容量
  • hasSizeLessThanOrEqualTo:小于等于指定容量
  • hasSizeBetween:在指定的范围之间
  • hasSameSizeAs:与指定的可迭代对象有相同的容量
  • contains:包含指定子元素
  • containsOnly:只包含指定子元素,忽略顺序
  • containsOnlyOnce:只包含给定值一次
  • containsOnlyNulls:只包含null元素而不包含其他元素
  • containsExactly:包含给定的值,而不包含其他值,此断言应仅用于具有一致迭代顺序的组(即不要与HashSet一起使用
  • containsExactlyInAnyOrder:包含给定的值,且不包含其他值,忽略顺序
  • containsExactlyInAnyOrderElementsOf:包含给定的值,且不包含其他值,忽略顺序
  • isSubsetOf:存在指定的所有元素
  • containsSequence:以正确的顺序包含指定值
  • doesNotContainSequence:不以正确的顺序包含指定值
  • containsSubsequence:验证实际组是否以正确的顺序包含给定的子序列(可能在它们之间有其他值
  • doesNotContainSubsequence:验证实际的组不包含给定的子序列,子序列是由一组有序的值定义的,它们之间可能有额外的值
  • doesNotContain:验证实际的组不包含给定的值
  • doesNotContainAnyElementsOf:验证实际不包含给定Iterable的任何元素(即none)
  • doesNotHaveDuplicates:不包含重复项
  • startsWith:以…开始
  • endsWith:以…结束
  • containsNull:至少包含一个Null
  • doesNotContainNull:不包含Null
  • are:验证每个元素值满足给定条件
  • areNot:验证每个元素值不满足给定条件
  • have:验证所有元素满足给定条件
  • doNotHave:验证所有元素不满足给定条件
  • areAtLeastOne/haveAtLeastOne:至少存在一个满足条件的元素
  • areAtLeast/haveAtLeast:至少有N个满足条件的元素
  • areAtMost/haveAtMost:至多有N个满足条件的元素
  • areExactly/haveExactly:恰好有N个满足条件的元素
  • hasAtLeastOneElementOfType:至少有一个元素具有指定的类型
  • hasOnlyElementsOfType:所有元素都具有指定的类型
  • doesNotHaveAnyElementsOfTypes:所有元素不属于指定的类型(包括子类)
  • hasOnlyElementsOfTypes:所有元素都是给定类型的实例
  • containsAll:包含给定Iterable的所有元素,无论顺序
  • containsAnyOf:至少包含给定值中的一个
  • containsAnyElementsOf:至少包含一个给定的Iterable
  • extracting:从Iterable的待测元素中提取给定字段或属性的值到一个新的Iterable中
  • extractingResultOf:在被测试的Iterable的元素上提取给定方法调用的结果到一个新的Iterable中
  • map:通过应用映射函数映射Iterable的test下的元素,结果列表成为test下的实例
  • flatExtracting:通过应用函数提取Iterable元素的值,并将结果连接到一个列表中
  • flatMap:通过应用给定的Function来映射被测试的Iterable元素,并将结果集合平展到列表中
  • containsOnlyOnceElementsOf:和containsOnlyOnce效果一致
  • filteredOn:过滤,保留指定
  • filteredOnNull:过滤,保留指定或Null
  • first:导航到第一个元素
  • last:导航到最后一个元素
  • element:导航到指定位置的元素
  • allMatch:所有元素都匹配谓词
//null或空
assertThat(new ArrayList<>()).isNullOrEmpty();
assertThat(new ArrayList<>()).isEmpty();
assertThat(Arrays.asList(1, 2)).isNotEmpty();

//容量
assertThat(Arrays.asList(1, 2)).hasSize(2);
assertThat(Arrays.asList(1, 2)).hasSizeGreaterThan(1);
assertThat(Arrays.asList(1, 2)).hasSizeGreaterThanOrEqualTo(2);
assertThat(Arrays.asList(1, 2)).hasSizeLessThan(3);
assertThat(Arrays.asList(1, 2)).hasSizeLessThanOrEqualTo(2);
assertThat(Arrays.asList(1, 2)).hasSameSizeAs(Arrays.asList(3, 4));

//包含
assertThat(Arrays.asList(1, 2, 3, 4)).contains(2);
assertThat(Arrays.asList(1, 2, 3, 4)).containsOnly(2, 1, 3, 4);
assertThat(Arrays.asList(1, 2, 3, 4)).containsOnlyOnce(2);
assertThat(Arrays.asList(null, null)).containsOnlyNulls();
assertThat(Arrays.asList(1, 2, 3)).containsExactly(1, 2, 3);
assertThat(Arrays.asList(1, 2, 3)).containsExactlyInAnyOrder(2, 1, 3);
assertThat(Arrays.asList(1, 2, 3)).containsSequence(1, 2);
assertThat(Arrays.asList(1, 2, 3)).doesNotContainSequence(1, 3);
assertThat(Arrays.asList(1, 2, 3, null)).containsNull();
assertThat(Arrays.asList(1, 2, 3)).doesNotContainNull();

//开头结尾
assertThat(Arrays.asList(1, 2, 3)).startsWith(1);
assertThat(Arrays.asList(1, 2, 3)).endsWith(3);

//条件
assertThat(Arrays.asList(1, 2, 3)).are(new Condition<Integer>(num -> num > 0, "正数"));
assertThat(Arrays.asList(1, 2, 3)).have(new Condition<Integer>(num -> num > 0, "正数"));

//类型
assertThat(Arrays.asList(1, 2, 3)).hasAtLeastOneElementOfType(Integer.class);
assertThat(Arrays.asList(1, 2, 3)).hasOnlyElementsOfType(Integer.class);
assertThat(Arrays.asList(1, 2, 3)).doesNotHaveAnyElementsOfTypes(String.class);
assertThat(Arrays.asList(1, 2, 3)).hasOnlyElementsOfType(Integer.class);

//提取
Map<String, Integer> map = new HashMap<>();
map.put("one", 1);
map.put("two", 2);
map.put("three", 3);
assertThat(map).extracting("one", "two")
        .contains(1, 2);

//过滤
assertThat(Arrays.asList(1, 3, 5, 7, 9)).filteredOn(e -> e > 5)
        .contains(7, 9);

//导航
assertThat(Arrays.asList(1, 2, 3, 4)).first()
        .isEqualTo(1);
assertThat(Arrays.asList(1, 2, 3, 4)).last()
        .isEqualTo(4);
assertThat(Arrays.asList(1, 2, 3, 4)).element(2)
        .isEqualTo(3);//下标从0开始

//谓词匹配
assertThat(Arrays.asList(1, 2, 3, 4)).allMatch(e -> e > 0);

2.11、数组断言

数组对象的断言都位于AbstractObjectArrayAssert类中:

  • isNullOrEmpty
  • isEmpty
  • isNotEmpty
  • hasSize
  • hasSizeGreaterThan
  • hasSizeGreaterThanOrEqualTo
  • hasSizeLessThan
  • hasSizeLessThanOrEqualTo
  • hasSizeBetween
  • hasSameSizeAs
  • contains
  • containsOnly
  • containsOnlyOnce
  • containsOnlyNulls
  • containsExactly
  • containsExactlyInAnyOrder
  • containsExactlyInAnyOrderElementsOf
  • isSubsetOf
  • containsSequence
  • doesNotContainSequence
  • containsSubsequence
  • doesNotContainSubsequence
  • doesNotContain
  • doesNotContainAnyElementsOf
  • doesNotHaveDuplicates
  • startsWith
  • endsWith
  • containsNull
  • doesNotContainNull
  • are
  • areNot
  • have
  • doNotHave
  • areAtLeastOne/haveAtLeastOne
  • areAtLeast/haveAtLeast
  • areAtMost/haveAtMost
  • areExactly/haveExactly
  • hasAtLeastOneElementOfType
  • hasOnlyElementsOfType
  • doesNotHaveAnyElementsOfTypes
  • hasOnlyElementsOfTypes
  • containsAll
  • containsAnyOf
  • containsAnyElementsOf
  • extracting
  • extractingResultOf
  • map
  • flatExtracting
  • flatMap
  • containsOnlyOnceElementsOf
  • filteredOn
  • filteredOnNull
  • first
  • last
  • element
  • allMatch

2.12、异常断言

异常断言位于AbstractThrowableAssert类中:

  • hasMessage:验证实际Throwable的消息是否等于给定的消息
  • hasCause:验证实际的Throwable具有与给定的原因相似的原因,即具有相同的类型和消息
  • hasCauseReference:相同引用的Throwable
  • hasNoCause:验证没有原因
  • hasMessageStartingWith:验证实际Throwable的消息是否以给定的描述开始
  • hasMessageContaining:验证实际Throwable的消息是否包含给定的描述
  • hasMessageContainingAll:验证实际Throwable的消息是否包含给定的所有描述
  • hasMessageNotContaining:验证实际Throwable的消息是否包含给定的描述
  • hasMessageNotContainingAny:验证实际Throwable的消息至少包含一个给定的描述
  • hasStackTraceContaining:验证实际Throwable的堆栈跟踪是否包含给定的描述
  • hasMessageMatching:验证实际Throwable的消息是否与给定的正则表达式匹配
  • hasMessageFindingMatch:验证实际Throwable的消息序列是否与给定的正则表达式匹配
  • hasMessageEndingWith:验证实际Throwable的消息是否以给定的描述结束
  • hasCauseInstanceOf:验证实际Throwable的原因是否是给定类型的实例
  • hasCauseExactlyInstanceOf:验证实际Throwable的原因恰好是给定类型的实例
  • hasRootCause:验证实际的Throwable具有与给定的类似的根源,即具有相同的类型和消息
  • hasRootCauseInstanceOf:验证实际Throwable的根本原因是给定类型的实例
  • hasRootCauseExactlyInstanceOf:验证实际Throwable的根本原因是恰好是给定类型的实例
  • hasRootCauseMessage:验证实际Throwable的根本原因的消息是否等于给定的消息
  • hasNoSuppressedExceptions:验证实际的Throwable没有抑制异常
  • hasSuppressedException:验证实际的Throwable具有与给定的异常相似的抑制异常,即具有相同的类型和消息
  • doesNotThrowAnyException:验证不抛出任何异常
//断言异常消息
Throwable throwable = new IllegalArgumentException("wrong amount 123");
assertThat(throwable).hasMessage("wrong amount 123")
        .hasMessage("%s amount %d", "wrong", 123)
        .hasMessageStartingWith("wrong")
        .hasMessageStartingWith("%s a", "wrong")
        .hasMessageContaining("wrong amount")
        .hasMessageContainingAll("wrong", "amount")
        .hasMessageEndingWith("123")
        .hasMessageEndingWith("amount %s", "123")
        .hasMessageMatching("wrong amount.*")
        .hasMessageNotContaining("right")
        .hasMessageNotContainingAny("right", "price");

//断言异常原因
NullPointerException cause = new NullPointerException("boom!");
Throwable t = new Throwable(cause);
assertThat(t).hasCause(cause)
        .hasCauseInstanceOf(NullPointerException.class)
        .hasCauseInstanceOf(RuntimeException.class)//可匹配父类
        .hasCauseExactlyInstanceOf(NullPointerException.class);//严格匹配,只能相同类型

assertThatExceptionOfType(RuntimeException.class)
        .isThrownBy(() -> {
            throw new RuntimeException(new IllegalArgumentException("boom!"));
        })
        .havingCause()
        .withMessage("boom!");

//断言异常根本原因
NullPointerException rootCause = new NullPointerException("null!");
Throwable err = new Throwable(new IllegalArgumentException(rootCause));
assertThat(err).hasRootCause(rootCause)
        .hasRootCauseMessage("null!")
        .hasRootCauseMessage("%s!", "null")
        .hasRootCauseInstanceOf(NullPointerException.class)
        .hasRootCauseInstanceOf(RuntimeException.class)
        .hasRootCauseExactlyInstanceOf(NullPointerException.class);

assertThatExceptionOfType(RuntimeException.class)
        .isThrownBy(() -> {
            throw new RuntimeException(new IllegalArgumentException(new NullPointerException("root error")));
        })
        .havingRootCause()
        .withMessage("root error");

//BDD风格
String[] names = {"Pier", "Pol", "Jak"};
Throwable thrown = catchThrowable(() -> {
    //数组越界
    System.out.println(names[9]);
});
then(thrown).isInstanceOf(ArrayIndexOutOfBoundsException.class)
        .hasMessageContaining("9");

//断言抛出者
assertThatThrownBy(() -> {
    throw new Exception("boom!");
}).isInstanceOf(Exception.class).hasMessageContaining("boom");

//断言异常类型
assertThatExceptionOfType(IOException.class)
        .isThrownBy(() -> {
            throw new IOException("boom!");
        })
        .withMessage("%s!", "boom")
        .withMessageContaining("boom")
        .withNoCause();

//断言没有异常
assertThatNoException().isThrownBy(() -> {
    System.out.println("OK");
});
thenNoException().isThrownBy(() -> {
    System.out.println("OK");
});
assertThatCode(() -> {
    System.out.println( "OK");
}).doesNotThrowAnyException();
thenCode(() -> {
    System.out.println("OK");
}).doesNotThrowAnyException();

2.13、逐字段递归比较

class Person {
    String name;
    double htight;
    Home home = new Home();

    public Person(String name, double htight) {
        this.name = name;
        this.htight = htight;
    }
}

class Home {
    Address address = new Address();
    Date ownedSince;
}

static class Address {
    int number;
    String street;
}

@Test
public void test1() {
    Person sherlock = new Person("Sherlock", 1.80);
    sherlock.home.ownedSince = new Date(123);
    sherlock.home.address.street = "Baker Street";
    sherlock.home.address.number = 221;

    Person sherlock2 = new Person("Sherlock", 1.80);
    sherlock2.home.ownedSince = new Date(123);
    sherlock2.home.address.street = "Baker Street";
    sherlock2.home.address.number = 221;

    //断言成功,逐字段递归比较
    assertThat(sherlock).usingRecursiveComparison()
            .isEqualTo(sherlock2);

    //断言失败,因为Person只比较引用
    assertThat(sherlock).isEqualTo(sherlock2);
}

可以在比较中忽略被测对象的字段,有几种方法可以指定要忽略的字段:

  • ignoringFields(String…​ fieldsToIgnore)
  • ignoringFieldsMatchingRegexes(String…​ regexes)
  • ignoringFieldsOfTypes(Class…​ typesToIgnore)
  • 嵌套字段可以这样指定:home.address.street

2.14、软断言

通过软断言,AssertJ 会收集所有断言错误,而不是在第一个错误处停止。由于软断言不会在第一个错误时失败,因此您需要告诉 AssertJ 何时报告捕获的断言错误,有不同的方法可以做到这一点:

  • 调用assertAll()(基本方法)
  • 使用JUnit 4 规则负责assertAll()每次测试后的调用
  • 使用提供的JUnit 5 扩展注入一个SoftAssertions或一个参数并在每次测试后BDDSoftAssertions调用assertAll()
  • 用一个AutoCloseableSoftAssertions
  • 使用assertSoftly静态方法
//构建一个SoftAssertions实例来记录所有断言错误
SoftAssertions softly = new SoftAssertions();

//使用softly.assertThat而不是通常的assertThat方法
softly.assertThat("George Martin").as("great authors").isEqualTo("JRR Tolkien");
softly.assertThat(42).as("response to Everything").isGreaterThan(100);
softly.assertThat("Gandalf").isEqualTo("Sauron");

//不要忘记调用assertAll(),否则不会报告断言错误!
softly.assertAll();

2.15、假设

假设为条件测试执行提供支持,如果满足假设,则测试正常执行,如果不满足,则测试将中止并标记为忽略。

当继续执行给定的测试方法没有意义时,通常会使用假设 - 典型的用法是根据给定的操作系统/环境运行测试。

所有 AssertJ 假设都是Assumptions类中的静态方法,它们与断言 API 匹配,但是名称assumeThat而不是assertThat.

//假设的条件
assumeThat("hello").isLowerCase();
//只有假设条件成立,才继续执行
assertThat(1).isLessThan(10);

3、Guava模块

AssertJ Guava 需要 Java 8 或更高版本。

<dependency>
  <groupId>org.assertj</groupId>
  <artifactId>assertj-guava</artifactId>
  <version>3.25.1</version>
  <scope>test</scope>
</dependency>

3.1、简单示例

该类org.assertj.guava.api.Assertions是开始使用 AssertJ Guava 所需的唯一类。

import static org.assertj.guava.api.Assertions.assertThat;
import static org.assertj.guava.api.Assertions.entry;

// Multimap assertions
Multimap<String, String> actual = ArrayListMultimap.create();
actual.putAll("Lakers", newArrayList("Kobe Bryant", "Magic Johnson", "Kareem Abdul Jabbar"));
actual.putAll("Spurs", newArrayList("Tony Parker", "Tim Duncan", "Manu Ginobili"));

assertThat(actual).containsKeys("Lakers", "Spurs");
assertThat(actual).contains(entry("Lakers", "Kobe Bryant"), entry("Spurs", "Tim Duncan"));

// Multiset assertions
Multiset<String> actual = HashMultiset.create();
actual.add("shoes", 2);

assertThat(actual).contains(2, "shoes");
assertThat(actual).containsAtLeast(1, "shoes");
assertThat(actual).containsAtMost(3, "shoes");

// Range assertions
Range<Integer> range = Range.closed(10, 12);

assertThat(range).isNotEmpty()
                 .contains(10, 11, 12)
                 .hasClosedLowerBound()
                 .hasLowerEndpointEqualTo(10)
                 .hasUpperEndpointEqualTo(12);

// Table assertions
Table<Integer, String, String> bestMovies = HashBasedTable.create();

bestMovies.put(1970, "Palme d'Or", "M.A.S.H");
bestMovies.put(1994, "Palme d'Or", "Pulp Fiction");
bestMovies.put(2008, "Palme d'Or", "Entre les murs");
bestMovies.put(2000, "Best picture Oscar", "American Beauty");
bestMovies.put(2011, "Goldener Bär", "A Separation");

assertThat(bestMovies).hasRowCount(5).hasColumnCount(3).hasSize(5)
                      .containsValues("American Beauty", "A Separation", "Pulp Fiction")
                      .containsCell(1994, "Palme d'Or", "Pulp Fiction")
                      .containsColumns("Palme d'Or", "Best picture Oscar", "Goldener Bär")
                      .containsRows(1970, 1994, 2000, 2008, 2011);

4、Joda Time模块

AssertJ Joda Time 主要版本取决于不同的 Java 版本:

  • AssertJ Joda Time 2.x 需要 Java 8 或更高版本
  • AssertJ Joda Time 1.x 需要 Java 7 或更高版本
<!-- 日期工具栏依赖 -->
<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.9.4</version>
</dependency>
<dependency>
  <groupId>org.assertj</groupId>
  <artifactId>assertj-joda-time</artifactId>
  <!-- use 1.1.0 for Java 7 projects -->
  <version>2.2.0</version>
  <scope>test</scope>
</dependency>

4.1、简单示例

该类org.assertj.jodatime.api.Assertions是开始使用 AssertJ Joda Time 所需的唯一类。

import static org.assertj.jodatime.api.Assertions.assertThat;
DateTime dateTime1 = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeZone.UTC);
DateTime dateTime2 = new DateTime(2001, 1, 1, 0, 0, 0, DateTimeZone.UTC);

assertThat(dateTime1).isBefore(dateTime2);
assertThat(dateTime2).isAfterOrEqualTo(dateTime1);

//自动转换字符串
assertThat(new DateTime("2000-01-01")).isEqualTo("2000-01-01");

//datetime比较忽略秒和毫秒
dateTime1 = new DateTime(2000, 1, 1, 23, 50, 0, 0, DateTimeZone.UTC);
dateTime2 = new DateTime(2000, 1, 1, 23, 50, 10, 456, DateTimeZone.UTC);
assertThat(dateTime1).isEqualToIgnoringSeconds(dateTime2);

DateTime utcTime = new DateTime(2013, 6, 10, 0, 0, DateTimeZone.UTC);
DateTime cestTime = new DateTime(2013, 6, 10, 2, 0, DateTimeZone.forID("Europe/Berlin"));
assertThat(utcTime).as("in UTC time").isEqualTo(cestTime);

4.2、常用断言

1)、LocalDate
  • hasYear(int expectedYear):验证实际年份LocalDate是否等于给定年份
  • hasMonthOfYear(int expectedMonthOfYear):验证实际月份LocalDate是否等于给定月份
  • hasDayOfMonth(int expectedDayOfMonth):验证实际的月份日期LocalDate是否等于给定的月份日期
  • isAfter(org.joda.time.LocalDate other)
    验证实际值是否LocalDate严格位于给定值之后
  • isAfter(String localDateAsString):isAfter(DateTime)使用LocalDate给定构建的调用String必须遵循 ISO8601 格式yyyy-MM-dd
  • isAfterOrEqualTo(org.joda.time.LocalDate other):验证实际值LocalDate是否晚于或等于给定值
  • isAfterOrEqualTo(String localDateAsString):isAfterOrEqualTo(DateTime)使用LocalDate给定构建的调用String必须遵循 ISO8601 格式yyyy-MM-dd
  • isBefore(org.joda.time.LocalDate other):验证实际值是否LocalDate严格位于给定值之前
  • isBefore(String localDateAsString):isBefore(DateTime)使用LocalDate给定构建的调用String必须遵循 ISO8601 格式yyyy-MM-dd
  • isBeforeOrEqualTo(org.joda.time.LocalDate other):验证实际值是否LocalDate早于或等于给定值
  • isBeforeOrEqualTo(String localDateAsString):isBeforeOrEqualTo(DateTime)使用LocalDate给定构建的调用String必须遵循 ISO8601 格式yyyy-MM-dd
  • isEqualTo(String localDateAsString):调用AbstractAssert.isEqualTo(Object)传递LocalDate给定的构建String,必须遵循 ISO8601 格式yyyy-MM-dd
  • isIn(String…​ dateTimesAsString):isIn(DateTime…​)使用从给定字符串构建的日期时间进行调用,该字符串必须遵循 ISO8601 格式yyyy-MM-dd
  • isNotEqualTo(String localDateAsString):isNotEqualTo(DateTime)使用LocalDate给定构建的调用String必须遵循 ISO8601 格式yyyy-MM-dd
  • isNotIn(String…​ localDatesAsString):isNotIn(org.joda.DateTime…​)使用从给定字符串构建的 DateTime 进行调用,该字符串必须遵循 ISO8601 格式yyyy-MM-dd
assertThat(new LocalDate(2000, 1, 1))
        .hasYear(2000)
        .hasMonthOfYear(1)
        .hasDayOfMonth(1);

LocalDate date1 = new LocalDate(2000, 1, 1);
LocalDate date2 = new LocalDate(2001, 1, 1);
assertThat(date1)
        .isBefore(date2)
        .isBeforeOrEqualTo(date2);
assertThat(date2)
        .isAfter(date1)
        .isAfterOrEqualTo(date1);
2)、LocalDateTime
  • hasDayOfMonth(int expectedDayOfMonth):验证实际的月份日期LocalDateTime是否等于给定的月份日期
  • hasHourOfDay(int expectedHourOfDay):验证实际小时数LocalDateTime是否等于给定小时数
  • hasMillisOfSecond(int expectedMillisOfSecond):验证实际的毫秒数LocalDateTime是否等于给定的毫秒数
  • hasMinuteOfHour(int expectedMinuteOfHour):验证实际分钟数是否LocalDateTime等于给定分钟数
  • hasMonthOfYear(int expectedMonthOfYear):验证实际月份LocalDateTime是否等于给定月份
  • hasSecondOfMinute(int expectedSecondOfMinute):验证实际秒数LocalDateTime是否等于给定秒数
  • hasYear(int expectedYear):验证实际年份LocalDateTime是否等于给定年份
  • isAfter(org.joda.time.LocalDateTime other):验证实际值是否LocalDateTime严格位于给定值之后
  • isAfter(String localDateTimeAsString)
    isAfter(DateTime)使用LocalDateTime给定构建的调用String必须遵循ISO DateTime 格式
  • isAfterOrEqualTo(org.joda.time.LocalDateTime other)
    验证实际值LocalDateTime是否晚于或等于给定值
  • isAfterOrEqualTo(String localDateTimeAsString):isAfterOrEqualTo(DateTime)使用LocalDateTime给定构建的调用String必须遵循ISO DateTime 格式。
  • isBefore(org.joda.time.LocalDateTime other):验证实际值是否LocalDateTime严格位于给定值之前
  • isBefore(String localDateTimeAsString):isBefore(DateTime)使用LocalDateTime给定构建的调用String必须遵循ISO DateTime 格式。
  • isBeforeOrEqualTo(org.joda.time.LocalDateTime other):验证实际值是否LocalDateTime早于或等于给定值
  • isBeforeOrEqualTo(String localDateTimeAsString)
    isBeforeOrEqualTo(DateTime)使用LocalDateTime给定构建的调用String必须遵循ISO DateTime 格式。
  • isEqualTo(String localDateTimeAsString)
    调用AbstractAssert.isEqualTo(Object)传递LocalDateTime从给定的构建String必须遵循ISO DateTime 格式。
  • isEqualToIgnoringHours(org.joda.time.LocalDateTime other)
    验证实际值和给定值是否LocalDateTime具有相同的年、月和日字段(比较时忽略小时、分钟、秒和毫秒字段)
  • isEqualToIgnoringMinutes(org.joda.time.LocalDateTime other):验证实际值和给定值是否LocalDateTime具有相同的年、月、日和小时字段(比较中忽略分、秒和毫秒字段)
  • isEqualToIgnoringSeconds(org.joda.time.LocalDateTime other):验证实际值和给定值是否LocalDateTime具有相同的年、月、日、小时和分钟字段(相比之下,秒和毫秒字段被忽略)
  • isEqualToIgnoringMillis(org.joda.time.LocalDateTime other):验证实际值和给定值是否LocalDateTime具有相同的年、月、日、小时、分钟和秒字段(比较时忽略毫秒字段)
  • isIn(String…​ localDateTimesAsString):isIn(DateTime…​)使用从给定字符串构建的日期时间进行调用,该字符串必须遵循ISO 日期时间格式
  • isNotEqualTo(String localDateTimeAsString)
    isNotEqualTo(DateTime)使用LocalDateTime给定构建的调用String必须遵循ISO 日期时间格式
  • isNotIn(String…​ dateTimesAsString):isNotIn(org.joda.DateTime…​)使用从给定字符串构建的 DateTime 进行调用,该字符串必须遵循ISO DateTime 格式
assertThat(new LocalDateTime(2000, 1, 1, 0, 0, 0))
        .hasYear(2000)
        .hasMonthOfYear(1)
        .hasDayOfMonth(1)
        .hasHourOfDay(0)
        .hasMinuteOfHour(0)
        .hasSecondOfMinute(0)
        .hasMillisOfSecond(0);

LocalDateTime dateTime1 = new LocalDateTime(2000, 1, 1, 0,0, 0);
LocalDateTime dateTime2 = new LocalDateTime(2001, 1, 1, 0,0, 0);
assertThat(dateTime1)
        .isBefore(dateTime2)
        .isBeforeOrEqualTo(dateTime2);
assertThat(dateTime2)
        .isAfter(dateTime1)
        .isAfterOrEqualTo(dateTime1);
3)、DateTime
  • hasDayOfMonth(int expectedDayOfMonth):验证实际的月份日期DateTime是否等于给定的月份日期
  • hasHourOfDay(int expectedHourOfDay):验证实际小时数DateTime是否等于给定小时数
  • hasMillisOfSecond(int expectedMillisOfSecond):验证实际的毫秒数DateTime是否等于给定的毫秒数
  • hasMinuteOfHour(int expectedMinuteOfHour):验证实际分钟数是否DateTime等于给定分钟数
  • hasMonthOfYear(int expectedMonthOfYear):验证实际月份DateTime是否等于给定月份
  • hasSecondOfMinute(int expectedSecondOfMinute):验证实际秒数DateTime是否等于给定秒数
  • hasYear(int expectedYear)
    验证实际年份DateTime是否等于给定年份
  • isAfter(org.joda.time.DateTime other):验证实际值是否DateTime严格位于给定值之后
  • isAfter(String dateTimeAsString)
    isAfter(DateTime)使用DateTime给定构建的调用String必须遵循ISO DateTime 格式。
  • isAfterOrEqualTo(org.joda.time.DateTime other)
    验证实际值DateTime是否晚于或等于给定值
  • isAfterOrEqualTo(String dateTimeAsString):isAfterOrEqualTo(DateTime)使用DateTime给定构建的调用String必须遵循ISO DateTime 格式。
  • isBefore(org.joda.time.DateTime other):验证实际值是否DateTime严格位于给定值之前
  • isBefore(String dateTimeAsString):isBefore(DateTime)使用DateTime给定构建的调用String必须遵循ISO DateTime 格式。
  • isBeforeOrEqualTo(org.joda.time.DateTime other):验证实际值是否DateTime早于或等于给定值
  • isBeforeOrEqualTo(String dateTimeAsString)
    isBeforeOrEqualTo(DateTime)使用DateTime给定构建的调用String必须遵循ISO DateTime 格式。
  • isEqualTo(org.joda.time.DateTime expected):验证实际值是否DateTime等于实际值 DateTimeZone 中给定的值
  • isEqualTo(String dateTimeAsString):isEqualTo(DateTime)使用DateTime给定构建的调用String必须遵循ISO DateTime 格式
  • isEqualToIgnoringHours(org.joda.time.DateTime other):验证实际值和给定值是否DateTime具有相同的年、月和日字段(比较时忽略小时、分钟、秒和毫秒字段)
  • isEqualToIgnoringMinutes(org.joda.time.DateTime other):验证实际值和给定值是否DateTime具有相同的年、月、日和小时字段(比较中忽略分、秒和毫秒字段)
  • isEqualToIgnoringSeconds(org.joda.time.DateTime other):验证实际值和给定值是否DateTime具有相同的年、月、日、小时和分钟字段(相比之下,秒和毫秒字段被忽略)
  • isEqualToIgnoringMillis(org.joda.time.DateTime other):验证实际值和给定值是否DateTime具有相同的年、月、日、小时、分钟和秒字段(比较时忽略毫秒字段)
  • isIn(org.joda.time.DateTime…​ expected)
    验证实际值DateTime是否等于DateTime实际值的 DateTimeZone 中给定的值之一
assertThat(new DateTime(2000, 1, 1, 0, 0, 0, 0))
        .hasYear(2000)
        .hasMonthOfYear(1)
        .hasDayOfMonth(1)
        .hasHourOfDay(0)
        .hasMinuteOfHour(0)
        .hasSecondOfMinute(0)
        .hasMillisOfSecond(0);
DateTime dateTime1 = new DateTime(2000, 1, 1, 0,0, 0);
DateTime dateTime2 = new DateTime(2001, 1, 1, 0,0, 0);
assertThat(dateTime1)
        .isBefore(dateTime2)
        .isBeforeOrEqualTo(dateTime2);
assertThat(dateTime2)
        .isAfter(dateTime1)
        .isAfterOrEqualTo(dateTime1);

5、Neo4j模块

暂略…

6、DB模块

AssertJ-DB 提供断言来测试数据库中的数据。它需要 Java 8 或更高版本,并且可以与 JUnit 或 TestNG 一起使用。

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.23</version>
</dependency>
<dependency>
  <groupId>org.assertj</groupId>
  <artifactId>assertj-db</artifactId>
  <version>2.0.2</version>
  <scope>test</scope>
</dependency>

6.1、简单示例

该类org.assertj.db.api.Assertions.assertThat是开始使用 AssertJ Joda Time 所需的唯一类。

假设数据库包含此MEMBERS表:

在这里插入图片描述

//创建mysql数据源
MysqlDataSource dataSource = new MysqlDataSource();
dataSource.setURL("jdbc:mysql:xxx:3306/demo");
dataSource.setUser("root");
dataSource.setPassword("123456");
//创建表
Table table = new Table(dataSource, "members");
//检查列
assertThat(table).column("name")
        .value().isEqualTo("Hewson")
        .value().isEqualTo("Evans")
        .value().isEqualTo("Clayton")
        .value().isEqualTo("Mullen");
//检查行
assertThat(table).row(1)
        .value().isEqualTo(2)
        .value().isEqualTo("Evans")
        .value().isEqualTo("David Howell")
        .value().isEqualTo("The Edge")
        .value().isEqualTo(DateValue.of(2008, 8, 1))
        .value().isEqualTo(1.77);
AssertJ 是 JAVA 的流畅断言库。示例代码:// unique entry point to get access to all assertThat methods and utility methods (e.g. entry) import static org.assertj.core.api.Assertions.*;  // common assertions assertThat(frodo.getName()).isEqualTo("Frodo"); assertThat(frodo).isNotEqualTo(sauron)                  .isIn(fellowshipOfTheRing);  // String specific assertions assertThat(frodo.getName()).startsWith("Fro")                            .endsWith("do")                            .isEqualToIgnoringCase("frodo");  // collection specific assertions assertThat(fellowshipOfTheRing).hasSize(9)                                .contains(frodo, sam)                                .doesNotContain(sauron);  // using extracting magical feature to check fellowshipOfTheRing characters name :) assertThat(fellowshipOfTheRing).extracting("name").contains("Boromir", "Gandalf", "Frodo", "Legolas")                                                   .doesNotContain("Sauron", "Elrond");  // map specific assertions, ringBearers initialized with the elves rings and the one ring bearers. assertThat(ringBearers).hasSize(4)                        .contains(entry(oneRing, frodo), entry(nenya, galadriel))                        .doesNotContainEntry(oneRing, aragorn);  // and many more assertions : dates, file, numbers, exceptions ... 标签:AssertJ
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值