断言

什么是断言

断言就是专门用来验证输出和期望是否一致的一个工具。换句话说断言就是判断一个方法所产生的结果是否符合你期望的那个结果。

例如:如果你写个一个方法 sum( ) 用来计算两个数的和,那现在你想验证下你这个方法计算 1+1 是不是 2,你可以使用 assertEquals 断言方法,就像这样 assertEquals(2, sum(1,1)) ,如果 你 sum 方法计算 1+1 后返回的不是 2,那么测试方法断言就失败了这里就会报错提示你;如果返回的就是预期的2,那么就会继续执行 assertEquals 断言后的语句。

断言方法

junt5 提供了许多断言方法

断言方法

说明

assertEquals(expected, actual, message)

如果预期值 expected 不等于实际返回值 actual ,则断言失败。

assertNotEquals(expected, actual, message)

如果预期值 expected 等于实际返回值 actual ,则断言失败。

assertTrue(booleanExpression, message)

如果 booleanExpression 不是 true ,则断言失败。

assertFalse(booleanExpression, message)

如果 booleanExpression 不是 false ,则断言失败。

assertNull(actual, message)

如果 actual 不是 null ,则断言失败。

assertNotNull(actual, message)

如果 actual 是 null ,则断言失败。

assertSame(object1, object2, message)

如果两个对象引用没有指向同一个对象,则断言失败

assertNotSame(object1, object2, message)

如果两个对象引用指向同一个对象,则断言失败

assertArrayEquals(object1, object2, message)

如果方两个数组不相等,则断言失败

assertIterableEquals(Iterable1,Iterable2, message)

如果方两个列表集合的元素顺序或大小不相等,则断言失败

assertTimeout(expectedTimeout, executable, message)

如果执行的方法超过预期的时间,则断言失败(没执行完的代码会继续执行)

assertTimeoutPreemptively(expectedTimeout, executable, message)

如果执行的方法超过预期的时间,则断言失败(没执行完的代码会结束执行)

fail(failmessage)

抛出异常

message

message :上面这些断言方法里的 message 参数是可选的,当有 message 参数时如果断言失败时就会输出 message 内容;若没有 message 参数,断言失败则默认提示org.opentest4j.AssertionFailedError,例如:

//如果断言失败会报错org.opentest4j.AssertionFailedError
assertEquals(3, sum(1,1));
//如果断言失败会报错org.opentest4j.AssertionFailedError: 断言失败啦!sum(1,1)得到的结果不是预期的2,请检查sum方法!
assertEquals(2, sum(1,1),"断言失败啦!sum(1,1)得到的结果不是预期的2,请检查sum方法!");

fail 断言方法

fail 断言方法:上面的最后一个 fail 断言方法用来抛出异常,使测试方法运行到 fail 方法时立即失败终止(如果是运行的整个测试类,测试类里的其他测试方法将会继续运行,只会终止当前测试方法)。fail 方法一般用于当代码执行到了某个不应该被到达的分支时使用 fail 方法终止测试方法并给出提示信息;或者在catch块中抛出异常信息。示例:

@Test
public void demo() {
    if ("a".equals("b")) {
        System.out.println("a等于b");
    }else {
        fail("a不等于b,抛出错误");
    }
}
​
@Test
public void divisionCheck() {
    try {
        int a=2/0;
    } catch (Exception e) {
        fail(e.getMessage());
    }
}

assertIterableEquals

  • assertIterableEquals:用于比较两个Iterable对象(如List、Set等)中的元素是否相等(元素在集合对象中的顺序要一致),不需要这两个对象具有相同的类型。

List<String> arrList = new ArrayList<>(asList("Java", "Junit", "Test"));
List<String> linList = new LinkedList<>(asList("Java", "Junit", "Test"));
//arrList和linList虽然一个是ArrayList一个是LinkedList类型,但他们元素都相同,所以断言成功
assertIterableEquals(arrList, linList);

示例

@DisplayName("断言测试类")
public class AssertTest {
​
  @DisplayName("断言测试方法")
  @Test
  public void testAssertions() {
      String str1 = new String("abc");
      String str2 = new String("abc");
      String str3 = null;
      String str4 = "abc";
      String str5 = "abc";
      int val1 = 5;
      int val2 = 6;
      String[] expectedArray = {"one", "two", "three"};
      String[] resultArray = {"one", "two", "three"};
      List<String> arrList = new ArrayList<>(asList("Java", "Junit", "Test"));
      List<String> linList = new LinkedList<>(asList("Java", "Junit", "Test"));
​
      assertEquals(str1, str2);
      assertNotEquals(3, 2, "error");
      assertTrue(val1 < val2);
      assertFalse(val1 > val2);
      assertNotNull(str1);
      assertNull(str3);
      assertSame(str4, str5, "断言失败,str4和str5指向的对象不一样");
      assertNotSame(str1, str3);
      assertArrayEquals(expectedArray, resultArray);
      assertIterableEquals(arrList, linList);
      assertTimeout(
              Duration.ofSeconds(2),
              () -> {
                  Thread.sleep(1000);
              }
      );
  }
}

assertThat断言

虽然上面的一些断言方法已经满足了日常的一些测试,但是还不够丰富和灵活。 例如:如果你一个字符串是只有等于 “abcdef”,并且长度是6,以ab开始,并且包含 de 才算断言成功,那你需要写好几个断言语句或者判断方法,而 assertThat 就可以很方便的做到这一点。

assertThat 断言是第三方库 AssertJ-core 所提供的方法,AssertJ-core 提供了一组类和实用方法,使我们能够轻松地编写流畅而漂亮的断言。

在 pom.xml 中添加 AssertJ-core 依赖:

 <!-- assertj-core用于单元测试中使用assertThat断言-->
<dependency>
  <groupId>org.assertj</groupId>
  <artifactId>assertj-core</artifactId>
  <version>3.24.2</version>
  <scope>test</scope>
</dependency>

assertThat断言挺简单的,下面会用一些实例来快速介绍使用 assertThat 对常见类型的断言使用。

int断言

@Test
public void intAssertThat() {
    int a = 22;
    //只有a为大于10小于30并且等于22时,断言才成功
    assertThat(a)
            .isGreaterThan(10)
            .isLessThan(30)
            .isEqualTo(22);
}

字符断言

@Test
public void intAssertThat() {
    //只有c不等于a,且在 Unicode 表中,且大于w(即在w之后),且是小写时断言才成功
    char c = 'x';
    assertThat(c)
            .isNotEqualTo('a')
            .inUnicode()
            .isGreaterThanOrEqualTo('w')
            .isLowerCase();
}

字符串断言

@Test
public void charAssertThat() {
    //字符串断言 只有str1等于str2,并且str1长度是11,包含“123”,以“ab”开头,以“fg”结尾 时断言才成功
    String str1 = "abcd1234efg";
    String str2 = new String("abcd1234efg");
    assertThat(str1)
            .isEqualTo(str2)
            .hasSize(11)
            .contains("123")
            .startsWith("ab")
            .endsWith("fg");
}

boolean断言

@Test
public void boolAssertThat() {
    boolean bo1 = true;
    boolean bo2 = true;
    //只有bo1为true并且等于bo2时断言才成功
    assertThat(bo1)
            .isTrue()
            .isEqualTo(bo2);
}

List和数组断言

对 List 和数组断言:

@Test
public void listArrayAssertThat1() {
  //只有list1不为空(不为null且size大于0)且包含元素1,且包含元素3和4,且所有元素不为null,且等于list2 时,断言才成功
  List<String> list1 = Arrays.asList("1", "2", "3", "4");
  List<String> list2 = Arrays.asList("1", "2", "3", "4");
  assertThat(list1)
          .isNotEmpty()
          .contains("1")
          .containsSequence("3","4")
          .doesNotContainNull()
          .isEqualTo(list2);

  //只有array1不为null且包含元素3,且等于array2 ,且数组长度是3时,断言才成功      
  String[] array1 ={"1", "2", "3"};
  String[] array2 ={"1", "2", "3"};
  assertThat(array1)
          .isNotNull()
          .contains("3")
          .isEqualTo(array2)
          .hasSize(3);
}

对 List 的每个元素过滤断言:

@Test
public void listArrayAssertThat2() {
    List<String> list = Arrays.asList("1-a", "2-b", "3-c", "4-d","5-e ok");
    //只有list中每个元素都含有"-",并且至少有一个元素含有"ok"时,断言才成功
    assertThat(list)
            .allMatch(v->v.contains("-"))
            .anyMatch(v->v.contains("ok"));
}

对List的进行过滤得到新的一个List进行断言:

假设有Student类如下

public class Student {
  public String name;
  public int id;

  public Student(String name, int id) {
      this.name = name;
      this.id = id;
  }
    //省略name和id的get/set方法
    //...
}
@Test
public void listArrayAssertThat2() {
    List<Student> stuList = new ArrayList<>();
    stuList.add(new Student("Jerry",1));
    stuList.add(new Student("Tom",2));
    stuList.add(new Student("Lucy",3));

    //过滤筛选出 stuList 里所有 name 叫 Tom 的,然后断言其数量只有一个
    assertThat(stuList)
            .filteredOn(v->"Tom".equals(v.getName()))
            .hasSize(1);
}

再来一个例子:

@Test
public void listFilterAssertThat() {
    List<Student> stuList = new ArrayList<>();
    Student student1 = new Student("张三",1);
    Student student2 = new Student("李四",2);
    Student student3 = new Student("王五",3);
    stuList.add(student1);
    stuList.add(student2);
    stuList.add(student3);

    List<String> nameList = Arrays.asList("张三","李四","王五");

    //extracting函数调用 getName 获取所有学生的姓名为一个新的List,然后只有这个新的List包含元素李四,且这个新是List等于nameList,断言才成功
    assertThat(stuList)
            .extracting(Student::getName)
            .contains("李四")
            .isEqualTo(nameList);
}

Map断言

@Test
public void mapAssertThat() {
    Map<Integer, Integer> map = new HashMap<>();
    map.put(1, 5);
    map.put(2, 7);
    map.put(3, 15);
    //只有map不为空(不为null且size大于0),且包含key是2,且不包含key是10,且包含value是5,且包含键值分别是3和15时,断言才成功
    assertThat(map)
            .isNotEmpty()
            .containsKey(2)
            .doesNotContainKeys(10)
            .containsValue(5)
            .contains(entry(3, 15));
}

对象断言

断言两个对象的所有字段的值相等

@Test
public void objectAssertThat() {
//假设你有Student类
    Student student1 = new Student("张三",1);
    Student student2 = new Student("张三",1);
    //只有student1的所有字段的值分别等于student2的字段的值时,断言才成功
    assertThat(student1)
            .usingRecursiveComparison()
            .isEqualTo(student2);
}

对对象的字段进行断言:

@Test
public void objectAssertThat() {
    //假设你有Student类
    Student student = new Student("tom jeff",4);
    //student的name字段的值包含jeff时,断言才成功
    assertThat(student.getName())
            .contains("jeff");
​
    //student的id字段的值大于3小于5时,断言才成功
    assertThat(student.getId())
            .isLessThan(5)
            .isGreaterThan(3);
}