单元测试-断言机制
# 570.单元测试-断言机制
接下来说说断言(assertions)
# 简介
断言(assertions)是测试方法中的核心部分,用来对测试需要满足的条件进行验证。这些断言方法都是 org.junit.jupiter.api.Assertions 的静态方法。
JUnit 5 内置的断言主要用于检查业务逻辑返回的数据是否合理。在之前,我们运行一个测试方法,都是运行后观察其输出是否正确;而如果测试方法比较多,则需要逐个判断输出,不太方便;
为此,我们可以使用断言,也就是在程序运行之前,就预测结果,如果结果有误则抛异常。
断言机制还有一个好处:可以使用 Maven 的 test 生命周期,这样所有的测试运行结束以后,会有一个详细的测试报告。
断言的分类:
- 简单断言
- 数组断言
- 组合断言
- 异常断言
- 超时断言
- 快速失败
# 简单断言
比如,我们写了一个方法,我们要对其进行调用,并判断实际结果,和预期结果是否相等:
package com.peterjxl.learnspringbootwebadmin;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class Junit5Assertions {
int calulate(int i, int j){
return i + j;
}
@Test
void testSimpleAssertions(){
int calulate = calulate(3, 3);
Assertions.assertEquals(5, calulate);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
assertEquals 方法用来判断值是否相等,第一个参数是期望值,第二个则是实际值。运行结果:
org.opentest4j.AssertionFailedError:
预期:5
实际:6
2
3
4
我们还可以指定错误信息:
@Test
void testSimpleAssertions(){
int calulate = calulate(3, 3);
Assertions.assertEquals(5, calulate, "业务逻辑计算失败");
}
2
3
4
5
运行结果:
org.opentest4j.AssertionFailedError: 业务逻辑计算失败 ==>
预期:5
实际:6
2
3
更多方法:
方法 | 说明 |
---|---|
assertEquals | 判断两个对象或两个原始类型是否相等 |
assertNotEquals | 判断两个对象或两个原始类型是否不相等 |
assertSame | 判断两个对象引用是否指向同一个对象 |
assertNotSame | 判断两个对象引用是否指向不同的对象 |
assertTrue | 判断给定的布尔值是否为 true |
assertFalse | 判断给定的布尔值是否为 false |
assertNull | 判断给定的对象引用是否为 null |
assertNotNull | 判断给定的对象引用是否不为 null |
注意:如果一个方法中有 2 个断言,其中第一个断言失败了,后续的也不会执行
# 数组断言
通过 assertArrayEquals 方法来判断两个对象或原始类型的数组是否相等
@Test
public void array() {
Assertions.assertArrayEquals(new int[]{1, 2}, new int[] {1, 2});
}
2
3
4
PS:也可以传入报错信息
Assertions.assertArrayEquals(new int[]{1, 2}, new int[] {1, 2}, "数组内容不相等");
1
由于是相等的,因此运行后没有什么结果。而如果不等:
@Test
public void array() {
Assertions.assertArrayEquals(new int[]{1, 2}, new int[] {1, 2});
Assertions.assertArrayEquals(new int[]{2, 2}, new int[] {1, 2});
}
2
3
4
5
运行结果:
org.opentest4j.AssertionFailedError: array contents differ at index [0], expected: <2> but was: <1>
# 组合断言
有时候我们需要在一个方法中进行多个断言,每个断言都成功后,才算成功;此时就可以用组合断言,也就是 assertAll 方法,该接受多个 org.junit.jupiter.api.Executable 函数式接口的实例作为要验证的断言,可以通过 lambda 表达式很容易的提供这些断言
方法签名:
第一个方法签名,也就是我们可以传一个可变数组进去;
第二个方法签名,则说明可以传一个名字进去,相当于所有断言当成一个组,起个组名
举例:
@Test
@DisplayName("组合断言")
void all() {
Assertions.assertAll("test",
() -> Assertions.assertTrue(true && true, "结果不为true"),
() -> Assertions.assertEquals(1, 2, "结果不为1"));
}
2
3
4
5
6
7
# 异常断言
有时候我们可能要测试异常情况,因此需要方法抛出异常,如果没抛出则说明断言失败。
在 JUnit4 时期,想要测试方法的异常情况时,需要用@Rule 注解的 ExpectedException 变量,还是比较麻烦的。而 JUnit5 提供了一种新的断言方式 Assertions.assertThrows()
, 配合函数式编程就可以进行使用。
@Test
@DisplayName("异常测试")
public void exceptionTest() {
Assertions.assertThrows(
ArithmeticException.class,
() -> System.out.println(1 % 0),
"业务逻辑居然正常运行?");
}
2
3
4
5
6
7
8
# 超时断言
Junit5 还提供了 Assertions.assertTimeout()
为测试方法设置了超时时间
@Test
@DisplayName("超时测试")
public void timeoutTest() {
//如果测试方法时间超过1s将会异常
Assertions.assertTimeout(Duration.ofMillis(1000), () -> Thread.sleep(500));
}
2
3
4
5
6
# 快速失败
通过 fail 方法直接使得测试失败(用的较少):
@Test
@DisplayName("fail")
public void shouldFail() {
Assertions.fail("This should fail");
}
2
3
4
5
# mvn test
我们可以使用 Maven 的生命周期 test 来生成测试报告:
运行结果:
There are test failures.
Please refer to D:\Projects\LearnSpringBoot-Web-Admin\target\surefire-reports for the individual test results.
Please refer to dump files (if any exist) [date].dump, [date]-jvmRun[N].dump and [date].dumpstream.
2
3
4
打开该文件夹,可以看到每个测试类有个单独的文件:
例如 Junit5Test.txt 的内容:
-------------------------------------------------------------------------------
Test set: com.peterjxl.learnspringbootwebadmin.Junit5Test
-------------------------------------------------------------------------------
Tests run: 8, Failures: 0, Errors: 1, Skipped: 1, Time elapsed: 3.813 s <<< FAILURE! - in com.peterjxl.learnspringbootwebadmin.Junit5Test
testTimeout Time elapsed: 0.659 s <<< ERROR!
java.util.concurrent.TimeoutException: testTimeout() timed out after 500 milliseconds
2
3
4
5
6
# 最后
更多关于断言的说明,可以参考 官网文档 (opens new window)
已将本文源码上传到 Gitee (opens new window) 或 GitHub (opens new window) 的分支 demo18,读者可以通过切换分支来查看本文的示例代码