Spring Boot之——单元测试集成(Junit4&&Junit5)

整合Junit4

目的:掌握SpringBoot整合 Junit4 单元测试

步骤:

  1. 引入场景(test)依赖
  2. 编写测试类,添加注解

实现:

pom依赖:

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>

编写测试类,添加注解``@SpringBootTest和@RunWith(SpringRunner.class)`

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.itheima.sh;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
* @Description: SpringBoot 集成 Junit4
* @Version: V1.0
*/
@SpringBootTest
@RunWith(SpringRunner.class) // 集成 Spring IOC容器环境
public class Junit4Test {

@Before
public void testBefore(){
System.out.println("testBefore.......");
}

@Test
public void testOne(){
System.out.println("testOne.......");
}

@After
public void testAfter(){
System.out.println("testAfter.......");
}
}

执行测试类:

image-20210503110202337

整合Junit5

目的:掌握SpringBoot整合 Junit5单元测试及新特性

讲解:

Spring Boot 2.2.0 版本开始引入 JUnit 5 作为单元测试默认库,2.3.X版本还保留了Junit4版本测试,但是在2.4.X则不再支持Junit4(参考官方

作为最新版本的JUnit框架,JUnit5与之前版本的Junit框架有很大的不同。由三个不同子项目的几个不同模块组成。

JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage

image-20210503105101344

JUnit Platform: Junit Platform是在JVM上启动测试框架的基础,不仅支持Junit自制的测试引擎,其他测试引擎也都可以接入。

JUnit Jupiter: JUnit Jupiter提供了JUnit5的新的编程模型,是JUnit5新特性的核心。内部 包含了一个测试引擎,用于在Junit Platform上运行。

JUnit Vintage: 由于JUint已经发展多年,为了照顾老的项目,JUnit Vintage提供了兼容JUnit4.x,Junit3.x的测试引擎。

实现:

依赖不变:

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>

测试类中移除 @RunWith(SpringRunner.class) 注解,直接添加@SpringBootTest注解即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package com.itheima.sh;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;


/**
* @SpringBootTest 组合注解:
* @BootstrapWith(SpringBootTestContextBootstrapper.class)
* @ExtendWith(SpringExtension.class)
*/
@SpringBootTest // 注释则是 Junit5单独运行
@DisplayName("SpringBoot整合Junit5功能测试类")
public class Junit5Test {

@BeforeEach
public void testBeforeEach() {
System.out.println("testBeforeEach......");
}

@AfterEach
public void testAfterEach() {
System.out.println("testAfterEach......");
}

@Test
public void testTwo() throws Exception{
System.out.println("testTwo......");
}


@BeforeAll
public static void testBeforeAll() {
System.out.println("BeforeAll......");
}

@AfterAll
public static void testAfterAll() {
System.out.println("testAfterAll......");
}
}

运行整个测试类测试:

image-20210503111855757

小结:

  • @BeforeAll和@AfterAll 只会运行一次
  • @BeforeEach和@AfterEach 每个测试类的测试方法都会运行

Junit5扩展(了解)

JUnit5的注解与JUnit4的注解有所变化

参考官网:https://junit.org/junit5/docs/current/user-guide/#writing-tests-annotations

  • **@Test :**表示方法是测试方法。但是与JUnit4的@Test不同,他的职责非常单一不能声明任何属性,拓展的测试将会由Jupiter提供额外测试
  • **@ParameterizedTest :**表示方法是参数化测试,下方会有详细介绍
  • **@RepeatedTest :**表示方法可重复执行,下方会有详细介绍
  • **@DisplayName :**为测试类或者测试方法设置展示名称
  • **@BeforeEach :**表示在每个单元测试之前执行
  • **@AfterEach :**表示在每个单元测试之后执行
  • **@BeforeAll :**表示在所有单元测试之前执行
  • **@AfterAll :**表示在所有单元测试之后执行
  • **@Tag :**表示单元测试类别,类似于JUnit4中的@Categories
  • **@Disabled :**表示测试类或测试方法不执行,类似于JUnit4中的@Ignore
  • **@Timeout :**表示测试方法运行如果超过了指定时间将会返回错误
  • **@ExtendWith :**为测试类或测试方法提供扩展类引用

实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package com.itheima.sh;

import org.junit.jupiter.api.*;

import java.util.concurrent.TimeUnit;

import static org.junit.jupiter.api.Assertions.*;

//@SpringBootTest
@DisplayName("junit5功能测试类")
public class Junit5ExtTest {


/**
* 测试前置条件
*/
@DisplayName("测试前置条件")
@Test
void testassumptions(){
Assumptions.assumeTrue(false,"结果不是true");
System.out.println("111111");

}



/**
* 断言:前面断言失败,后面的代码都不会执行
*/
@DisplayName("测试简单断言")
@Test
void testSimpleAssertions() {
int cal = add(3, 2);
//相等
assertEquals(6, cal, "业务逻辑计算失败");
Object obj1 = new Object();
Object obj2 = new Object();
assertSame(obj1, obj2, "两个对象不同");
}

@Test
@DisplayName("array assertion")
void array() {
assertArrayEquals(new int[]{1, 2}, new int[]{1, 2}, "数组内容不相等");
}

@Test
@DisplayName("组合断言")
void all() {
/**
* 所有断言全部需要成功
*/
assertAll("test",
() -> assertTrue(true && true, "结果不为true"),
() -> assertEquals(1, 2, "结果不是1"));

System.out.println("=====");
}

@DisplayName("异常断言")
@Test
void testException() {

//断定业务逻辑一定出现异常
assertThrows(ArithmeticException.class, () -> {
int i = 10 / 0;
}, "业务逻辑居然正常运行?");
}

@DisplayName("快速失败")
@Test
void testFail(){
//xxxxx
if(1 == 2){
fail("测试失败");
}

}


int add(int i, int j) {
return i + j;
}

@Disabled
@DisplayName("测试方法2")
@Test
void test2() {
System.out.println(2);
}

@RepeatedTest(5)
@Test
void test3() {
System.out.println(5);
}

/**
* 规定方法超时时间。超出时间测试出异常
*
* @throws InterruptedException
*/
@Timeout(value = 500, unit = TimeUnit.MILLISECONDS)
@Test
void testTimeout() throws InterruptedException {
Thread.sleep(600);
}
}

扩展学习:https://zhuanlan.zhihu.com/p/111706639