单元测试
JUnit5 的变化
Spring Boot 2.2.0 版本开始引入 JUnit 5 作为单元测试默认库
作为最新版本的JUnit框架,JUnit5与之前版本的Junit框架有很大的不同。由三个不同子项目的几个不同模块组成。
JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage
- JUnit Platform: Junit Platform是在JVM上启动测试框架的基础,不仅支持Junit自制的测试引擎,其他测试引擎也都可以接入。
- JUnit Jupiter: JUnit Jupiter提供了JUnit5的新的编程模型,是JUnit5新特性的核心。内部 包含了一个测试引擎,用于在Junit Platform上运行。
- JUnit Vintage: 由于JUint已经发展多年,为了照顾老的项目,JUnit Vintage提供了兼容JUnit4.x,Junit3.x的测试引擎。
Junit是为了可以做所有的语言测试做准备
SpringBoot中的junit
我们在SpringBoot中支持使用Junit5进行做测试
我们正常使用junit是不能集合Spring注解进行自动注入的操作的。
在Spring中我们通过配置和其他注解的接入可以完成测试中使用自动注入功能
SpringBoot对于Junit5做了自动装配。我们可以更简便的使用Spring注解进行操作junit测试
操作
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
Started的好处就是该依赖中包含多个依赖不需要我们在去考虑版本之间的问题
结合SpringBoot中的自动配置。进行生成对应的configuration
编写测试类
import cn.HelloWrod;
import cn.dao.UserDao;
import cn.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.util.List;
@SpringBootTest(classes = HelloWrod.class)
public class Junit5test {
@Resource
private UserDao userDao;
@Test
public void TestJunit() {
List<User> users = userDao.selectList(null);
System.out.println("全部的用户个数:" + users.size());
}
}
常用注解
● @Test :表示方法是测试方法。但是与JUnit4的@Test不同,他的职责非常单一不能声明任何属性,拓展的测试将会由Jupiter提供额外测试
● @ParameterizedTest :表示方法是参数化测试,下方会有详细介绍
● @RepeatedTest :表示方法可重复执行,下方会有详细介绍
● @DisplayName :为测试类或者测试方法设置展示名称
● @BeforeEach :表示在每个单元测试之前执行
● @AfterEach :表示在每个单元测试之后执行
● @BeforeAll :表示在所有单元测试之前执行 在测试类上进行的操作就是可以所有的测试都执行
● @AfterAll :表示在所有单元测试之后执行
● @Tag :表示单元测试类别,类似于JUnit4中的@Categories
● @Disabled :表示测试类或测试方法不执行,类似于JUnit4中的@Ignore
● @Timeout :表示测试方法运行如果超过了指定时间将会返回错误
● @ExtendWith :为测试类或测试方法提供扩展类引用
断言
在测试方法中,可以通过断言进行判断一些值得条件。当不满足得时候会给出错误提示。
一个测试方法中,第一个断言执行失败,之后得断言也不会执行。
断言失败之后得非断言代码也不会执行
断言方法
方法 | 说明 |
---|
assertEquals | 判断两个对象或两个原始类型是否相等 | assertNotEquals | 判断两个对象或两个原始类型是否不相等 | assertSame | 判断两个对象引用是否指向同一个对象 | assertNotSame | 判断两个对象引用是否指向不同的对象 | assertTrue | 判断给定的布尔值是否为 true | assertFalse | 判断给定的布尔值是否为 false | assertNull | 判断给定的对象引用是否为 null | assertNotNull | 判断给定的对象引用是否不为 null |
断言失败会给出异常报告,异常报告可以自己去编写。
代替我们得测试方法中得sout打印操作
示例
判断对象是否是空
以上方法一次类推
判断值是否相等
带上断言报文
当一个断言失败其他断言不执行。·
组合断言
所有断言都成功才能执行之后得代码
数组断言
通过 assertArrayEquals 方法来判断两个对象或原始类型的数组是否相等
@Test
@DisplayName("array assertion")
public void array() {
assertArrayEquals(new int[]{1, 2}, new int[] {1, 2});
}
异常断言
在JUnit4时期,想要测试方法的异常情况时,需要用**@Rule注解的ExpectedException变量还是比较麻烦的。而JUnit5提供了一种新的断言方式Assertions.assertThrows()** ,配合函数式编程就可以进行使用。
@Test
@DisplayName("异常测试")
public void exceptionTest() {
ArithmeticException exception = Assertions.assertThrows(
ArithmeticException.class, () -> System.out.println(1 % 0));
}
超时断言
Junit5还提供了Assertions.assertTimeout() 为测试方法设置了超时时间
@Test
@DisplayName("超时测试")
public void timeoutTest() {
Assertions.assertTimeout(Duration.ofMillis(1000), () -> Thread.sleep(500));
}
快速失败
通过 fail 方法直接使得测试失败
@Test
@DisplayName("fail")
public void shouldFail() {
fail("This should fail");
}
前置条件(assumptions)
JUnit 5 中的前置条件(assumptions【假设】)类似于断言,不同之处在于不满足的断言会使得测试方法失败,而不满足的前置条件只会使得测试方法的执行终止。前置条件可以看成是测试方法执行的前提,当该前提不满足时,就没有继续执行的必要。
@DisplayName("前置条件")
public class AssumptionsTest {
private final String environment = "DEV";
@Test
@DisplayName("simple")
public void simpleAssume() {
assumeTrue(Objects.equals(this.environment, "DEV"));
assumeFalse(() -> Objects.equals(this.environment, "PROD"));
}
@Test
@DisplayName("assume then do")
public void assumeThenDo() {
assumingThat(
Objects.equals(this.environment, "DEV"),
() -> System.out.println("In DEV")
);
}
}
在这个部分可以观察到哪些测试方法执行的结果
当然我这里写的测试太少了
参数化测试
将指定的多个参数,进行一个一个进行测试。
不如说传入5个参数,测试方法就执行5次。
**针对传入值得方式有很多 以下几种 **
- @ValueSource: 为参数化测试指定入参来源,支持八大基础类以及String类型,Class类型
- @NullSource: 表示为参数化测试提供一个null的入参
- @EnumSource: 表示为参数化测试提供一个枚举入参
- @CsvFileSource:表示读取指定CSV文件内容作为参数化测试入参
- @MethodSource:表示读取指定方法的返回值作为参数化测试入参(注意方法返回需要是一个流)
示例
@ValueSources()测试
@ParameterizedTest
@ValueSource(strings = {"one", "two", "three"})
@DisplayName("参数化测试1")
public void parameterizedTest1(String string) {
System.out.println(string);
}
@MethodSource()测试
指定方法得返回值得到值
@ParameterizedTest
@MethodSource("method")
@DisplayName("方法来源参数")
public void testWithExplicitLocalMethodSource(String name) {
System.out.println(name);
}
static Stream<String> method() {
return Stream.of("apple", "banana");
}
指标监控
每一个SpringBoot,我们都可以通过actuator进行监控。
查看具体的一个Springboot的信息
SpringBoot1和SpringBoot2是不同的
actuator的版本区别
使用
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
actuator底层是借助micrometer核心的
yaml配置开启
management:
endpoints:
enabled-by-default: true
web:
exposure:
include: '*'
访问
http://localhost:8080/actuator
可以看到可以进行访问哪些监控页面
没有配置注解开启前
health:当前健康状态
info:当前应用详细信息
使用注解暴漏断点后
http://localhost:8080/actuator/beans
http://localhost:8080/actuator/configprops
http://localhost:8080/actuator/metrics
http://localhost:8080/actuator/metrics/jvm.gc.pause
http://localhost:8080/actuator/endpointName/detailPath
actuator后面的指定称之为Endpoint
java中的工具jconsole
可以进行监控,查看endpoint,但是为了方便操作我们还是通过web展示更加方便
- 通过cmd的命令jconsole。
- 进行指定java程序可以进行连接
看到很多程序运行的信息
Actuator Endpoint
ID | 描述 |
---|
auditevents | 暴露当前应用程序的审核事件信息。需要一个AuditEventRepository组件 。 | beans | 显示应用程序中所有Spring Bean的完整列表。 | caches | 暴露可用的缓存。 | conditions | 显示自动配置的所有条件信息,包括匹配或不匹配的原因。 | configprops | 显示所有@ConfigurationProperties 。 | env | 暴露Spring的属性ConfigurableEnvironment | flyway | 显示已应用的所有Flyway数据库迁移。 需要一个或多个Flyway 组件。 | health | 显示应用程序运行状况信息。 | httptrace | 显示HTTP跟踪信息(默认情况下,最近100个HTTP请求-响应)。需要一个HttpTraceRepository 组件。 | info | 显示应用程序信息。 | integrationgraph | 显示Spring integrationgraph 。需要依赖spring-integration-core 。 | loggers | 显示和修改应用程序中日志的配置。 | liquibase | 显示已应用的所有Liquibase数据库迁移。需要一个或多个Liquibase 组件。 | metrics | 显示当前应用程序的“指标”信息。 | mappings | 显示所有@RequestMapping 路径列表。 | scheduledtasks | 显示应用程序中的计划任务。 | sessions | 允许从Spring Session支持的会话存储中检索和删除用户会话。需要使用Spring Session的基于Servlet的Web应用程序。 | shutdown | 使应用程序正常关闭。默认禁用。 | startup | 显示由ApplicationStartup 收集的启动步骤数据。需要使用SpringApplication 进行配置BufferingApplicationStartup 。 | threaddump | 执行线程转储。 |
这些都不是默认开启的,shutdown是默认关闭的
Health Endpoint
健康检查端点,我们一般用于在云平台,平台会定时的检查应用的健康状况,我们就需要Health Endpoint可以为平台返回当前应用的一系列组件健康状况的集合。
重要的几点:
只要程序中的配置不错,正常执行,表示程序就是健康的
以上只显示是否健康,我们可以进行yaml配置显示详细信息
management:
endpoints:
enabled-by-default: true
web:
exposure:
include: '*'
endpoint:
health:
show-details: always
Metrics Endpoint
提供详细的、层级的、空间指标信息,这些信息可以被pull(主动推送)或者push(被动获取)方式得到;
指定开启和关闭
- 将总开关关闭
- 分开关进行一个一个指定打开
监控指标
可视化的页面,前面的监控指标可以看到都是请求返回json的形式
配置一个监控服务器。定时获取监控信息,将信息展示在页面中,可视化的查看
引入依赖
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>2.3.1</version>
</dependency>
主启动器开启
@EnableAdminServer
@SpringBootApplication
public class HelloWrod {
public static void main(String[] args) {
SpringApplication.run(HelloWrod.class,args);
}
}
断点信息放入监控中心
可以看到我们的监控中心并没有数据,所以我们需要将监控的数据放入
表示开启客户端
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.3.1</version>
</dependency>
yaml配置
management:
endpoints:
enabled-by-default: true #暴露所有端点信息
web:
exposure:
include: '*' #以web方式暴露
#表示开启客户端,指定的 服务路径
spring:
boot:
admin:
client:
url: http://localhost:8080
applications路径
进入应用墙
http://wsl-001:8080/wallboard
点击应用查看详细
针对于该监控页面操作很多,这里不多介绍
高级特性
Profile功能
为了方便多环境适配,springboot简化了profile功能。
快速切换多个环境,方便进行开发
操作
看到这里存在三个配置文件SpringBoot
三个配置文件都配置了name这个属性值
控制器展示
@Controller
public class Controlleryaml {
@Value("${name}")
private String name;
@RequestMapping("showname")
@ResponseBody
public String showName(){
return name;
}
}
发现打印了没有指定环境名称的配置文件
想要指定环境怎么办呢
SpringBoot默认读取的都是没有环境名称的配置文件。
所以我们在 application.格式 配置文件中进行指定环境
指定配置环境
spring:
profiles:
active: test
在jar包执行方式的时候也可以指定配置文件
配置文件优先级
位置优先级
Springboot 启动会扫描以下位置的application.yml文件作为Spring boot的默认配置文件
–file:./config/
–file:./
–classpath:/config/
–classpath:/
那么不同格式配置文件的优先级呢
properties>yaml
|