SpringBoot——在测试阶段验证Web表现层的接口是否正常

news2024/11/20 6:31:43

验证请求状态

之前我们实现了在测试环境中开启Web环境,并且在测试阶段发送虚拟请求,并看到了返回的结果,这次我们不止要看他的请求结果,还要看他的请求过程和请求状态

匹配请求状态

首先就是查看请求的状态。主要介绍的就是一个重要的类,也是我们这一节的核心类:MockMvcResultMatchers,这个类是一个结果匹配器,他会提供不同请求状态的请求对象,然后我们可以拿到本次请求的结果对象与他的请求状态的对象做对比,查看本次请求的状态,具体的代码如下:

操作代码

package com.spring;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.result.StatusResultMatchers;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@AutoConfigureMockMvc
public class SpringBootTest02ApplicationTests {
    @Test
    public void test(@Autowired MockMvc mockMvc) throws Exception {
        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/test");
//        获得本次请求的信息
        ResultActions perform = mockMvc.perform(builder);
//        获取请求状态信息
        StatusResultMatchers status = MockMvcResultMatchers.status();
//        获取请求成功时候的请求状态
        ResultMatcher ok = status.isOk();
//        添加对比,将请求成功的状态与本次请求的状态做对比,如果匹配成功则表示请求成功,如果匹配失败,则表示亲请求失败
            ResultActions resultActions = perform.andExpect(ok);
        System.out.println(resultActions);
    }
}

大致的流程就是首先获取本次请求的结果对象,然后获取请求成功时候的对象,两者进行对比,最终的结果就可以反映出请求的结果是否和我们的预期值相同,我们来看运行结果:
在这里插入图片描述
如果是请求成功的情况,他本身什么都不会输出,而如果是请求失败了,就会输出很多的信息,我们可以故意把他的请求地址指向一个不存在的地址让他找不到就能看到信息了:
在这里插入图片描述
这里改一下他的请求地址,改到一个不存在的地址,这次我们再次运行代码:
在这里插入图片描述
在这里插入图片描述
这里面的数据就很多了,但是大概的也分为这几个类别,最下面的就是我们这次的匹配结果,很显然,我们设置的预期值是OK,但是他的真实值是not found,很明显的匹配不上,他就告诉我们了。
在这里插入图片描述
当然这里面还有一个有意思的地方就是,如果你的预期值就是not found,那么如果你的请求真是没有找到,那么这个程序就不会报错,但是Controller不会被调用,信息也就不会显示出来。哈哈,很无用,谁会故意测试一个Bug呢。

匹配响应体

匹配响应体的过程和匹配相应状态的过程是一样的,只不过是调用的方法替换一下,之前是调用的status()方法,现在改成content()方法,流程都是一样的,设置期待值,与真实值做匹配,最终返回结果:
在这里插入图片描述

@Test
    public void textBody(@Autowired MockMvc mockMvc) throws Exception {
        MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/test");
        ResultActions perform = mockMvc.perform(requestBuilder);
        ContentResultMatchers content = MockMvcResultMatchers.content();
        ResultMatcher string = content.string("Test Controller ……");
        ResultActions resultActions = perform.andExpect(string);
    }

我们运行代码测试一下:
在这里插入图片描述
如果期待值和真实值是一样的,那么就会一切顺利,如果不一样,就会打印出很多的信息:
在这里插入图片描述
之前的信息就不用看了,都是一样的,关键在于后面的信息,预期值和实际值不一样,他会告诉我们请求体是什么,预期的请求体是什么,真实的请求体是什么。

匹配响应体(JSON)

匹配JSON数据和匹配String数据基本是一样的,只不过方法不是String()而是json(),然后预期值的内容也换成json字符串即可。
返回json,最简单的方法就是使用@ResponseBody注解的特性,返回一个对象然后自动将对象转换成json格式在屏幕上显示。
首先我们创建一个类,用于被返回:
在这里插入图片描述
这就一切从简了,有两个属性,然后用lombok提供接口方法。然后我们修改一下Controller,让他可以返回对象:
在这里插入图片描述
然后我们启动这个SpringBoot,然后访问一下这里看是不是能顺利的打印这个JSON文件:
在这里插入图片描述
好,他确实是输出了JSON字符串,剩下的就简单了,换一下方法,然后直接把这个JSON字符串赋值过去当作预期值,然后运行看一下效果:

@Test
    public void textBodyJson(@Autowired MockMvc mockMvc) throws Exception {
        MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/test");
        ResultActions perform = mockMvc.perform(requestBuilder);
        ContentResultMatchers content = MockMvcResultMatchers.content();
        ResultMatcher json = content.json("{\"id\":2,\"name\":\"JavaWeb编程\"}");
        ResultActions resultActions = perform.andExpect(json);
    }

在这里插入图片描述
直接复制之后,我们稍微更改一下,让他和真实值有点不同,好让他报错,然后我们看报错信息:
在这里插入图片描述
上面的信息就是我们的相应信息,下面的红色的字就是匹配的结果,他会告诉你是哪里的属性出现了问题,这里他就说是id属性,因为我就是修改了id属性,预期值是2,真实值是1 ,匹配不上。

匹配请求头

请求头的匹配流程和之前都是一样的,无非就是方法不一样而已,我们直接上代码:

@Test
    public void testHandler(@Autowired MockMvc mockMvc) throws Exception {
        MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/test");
        ResultActions perform = mockMvc.perform(requestBuilder);
        HeaderResultMatchers header = MockMvcResultMatchers.header();
//        匹配请求头中的键值对,定义规则,当相应的数据不是JSON格式的时候就会匹配不上
        ResultMatcher heade = header.string("Content-Type", "application/json");
        ResultActions resultActions = perform.andExpect(heade);

预期值是相应的数据类型是JSON格式,也就是说当相应的文件不是JSON格式的时候,就匹配不上就会报错,我们把之前的Controller修改一下:
在这里插入图片描述
让他的返回值类型编程String类型,这样在相应的时候就肯定不是JSON格式的了,然后我们启动测试看一下运行结果:
在这里插入图片描述
报错了,预期是是JSON类型,实际值是String类型。
可以看到在这种匹配测试的时候其实流程都是差不多的,就是切换一下使用的方法即可。

使用场景

这种匹配测试在使用的时候,一般会多个匹配规则一起使用,比如我们第一个会先匹配响应状态,然后再匹配请求体,最后是请求头,这样我们的规则会更完善,最终的匹配结果也最精准。
大致的代码如下所示

@Test
    public void TestMatching(@Autowired MockMvc mockMvc) throws Exception {
        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/tests");
        ResultActions perform = mockMvc.perform(builder);
//        首先测试请求状态
        StatusResultMatchers status = MockMvcResultMatchers.status();
        ResultMatcher ok = status.isNotFound();
        perform.andExpect(ok);
//        然后匹配请求体
        ContentResultMatchers content = MockMvcResultMatchers.content();
        ResultMatcher string = content.string("TestController ……");
        perform.andExpect(string);
//        最后匹配响应头
        HeaderResultMatchers header = MockMvcResultMatchers.header();
        ResultMatcher heade = header.string("Content-Type", "application/json");
        perform.andExpect(heade);
    }

当然,能测试的部分肯定不止这些,之前我们看到报错信息中:
在这里插入图片描述
这里面的内容都可以进行匹配测试,有兴趣的可以自己尝试一下

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/726214.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于 Arduino 库实现 ESP32 使能 WiFi AP + TCP Server 的应用

实现步骤&#xff1a; ESP32 开启 WiFi AP 模式创建 WiFi 热点定义 IP 地址创建 TCP Server 测试代码如下&#xff1a; #include <WiFi.h> #include <WiFiClient.h>const char* ssid "cc123"; const char* password "espressif";WiFiServ…

Python-年会抽奖

#!/usr/bin/python # coding:utf-8 # Author:Rauckimport randomclass WhoIsLuck:"""年会抽奖"""# 奖品gift [{name: 一等奖, limit: 3, desc: 泰国5日游手术费报销},{name: 二等奖, limit: 6, desc: iPhone14手机},{name: 三等奖, limit: 30, …

【Linux OS】华为openEuler操作系统与openGauss数据库安装及使用入门

华为openEuler操作系统与openGauss数据库安装及使用入门 1、软件下载1.1、openEuler1.2、openGauss1.3、Data Studio 2、系统安装2.1、创建虚拟机2.2、安装操作系统2.3、登录系统 3、数据库安装及设置3.1、数据库安装3.2、数据库管理3.3、数据库设置 4、数据库访问4.1、Navicat…

Redis:IO多路复用深度解析

目录 一、Multiplexing&#xff08;IO多路复用&#xff09;1.是什么2.能干嘛3.Reactor设计模式4.select, poll, epoll 都是I/O多路复用的具体的实现4.1 select方法4.2 poll方法4.3 epoll方法4.4 三个方法对比 5.5种 I/O 模型总结6.为什么3个都保有 一、Multiplexing&#xff08…

关于如何使用 python 下载 json 格式数据

本章节内容节自《python编程从入门到实践》第十六章&#xff0c;我们将从网络上下载数据&#xff0c;并对数据进行可视化。就可以对其进行分析甚至观察其规律和关联。 学习目标 我们将访问并可视化以下两种常见格式存储的数据&#xff1a; CSV 使用 Python 模块 CSV 来处理以 C…

SpringBoot整合EasyExcel 3.x

文章目录 1 EasyExcel 3.x1.1 简介1.2 引入依赖1.3 简单导出1.3.1 定义实体类1.3.2 自定义转换器1.3.3 定义接口 1.4 简单导入1.5 复杂导出1.5.1 引言1.5.2 自定义注解1.5.3 定义实体类1.5.4 数据映射与平铺1.5.5 自定义单元格合并策略1.5.6 定义接口 1 EasyExcel 3.x 1.1 简介…

string容器语法

文章目录 string容器string基本概念本质&#xff1a;string和char * 区别&#xff1a;特点&#xff1a; string构造函数示例 string赋值操作示例&#xff1a; string字符串拼接示例&#xff1a; string查找和替换示例&#xff1a; string字符串比较示例&#xff1a; string字符…

第六章 rabbitmq高可用集群

在服务之间会采用mq进行消息通信,而rabbitmq本身也如同consul一样,如果只有一个节点那么就可能出现宕机的问题,并且基于mq的特点我们是可以在多个服务之间使用同一个mq来相互通信,因此高可用的架构设计就必不可少 1、rabbitmq集群方案 主备 远程 镜像 多活 构建 2、…

[uni-app]设置运行到微信小程序

1、设置微信小程序开发工具路径 2、检查微信小程序开发工具是否开启了服务端口 服务端口要是没有开启&#xff0c;会报 initialize。 3、在uni-app开发工具中点击运行微信开发者工具&#xff0c;微信开发工具运行成功。

Spark架构体系

StandAlone模式是spark自带的集群运行模式&#xff0c;不依赖其他的资源调度框架&#xff0c;部署起来简单。 StandAlone模式又分为client模式和cluster模式&#xff0c;本质区别是Driver运行在哪里&#xff0c;如果Driver运行在SparkSubmit进程中就是Client模式&#xff0c;如…

谷歌Med-PaLM 2霸榜医学问答领域

谷歌IO大会上&#xff0c;谷歌CEO桑达尔・皮查伊&#xff08;Sundar Pichai&#xff09;向全世界AI开发者发布了谷歌最新的大型语言模型&#xff08;LLMs&#xff09;PaLM 2&#xff0c;作为对标OpenAI最新大模型GPT-4的竞品&#xff0c;PaLM 2展现出了强大的多语言和推理能力。…

概率论与数理统计发展历史简介

概率论与数理统计发展历史简介 1 介绍1.1 概述1.2 概率论发展历史1.3 统计学发展历史1.4 概率论演化 2 在线学习在线 概率与统计 视觉化学习 -- 布朗大学何志坚老师的数理统计讲义鸢尾花书--统计至简 参考 1 介绍 1.1 概述 概率论是与概率有关的数学分支。虽然有几种不同的概…

Linux内核模块开发 第 8 章

The Linux Kernel Module Programming Guide Peter Jay Salzman, Michael Burian, Ori Pomerantz, Bob Mottram, Jim Huang译 断水客&#xff08;WaterCutter&#xff09;源 LKMPG 8 sysfs: 与模块交互 sysfs 允许用户通过读写模块中的变量实现与内核模块的交互。这个特性在…

leetcode907. 子数组的最小值之和(单调栈-java)

子数组的最小值之和 leetcode907. 子数组的最小值之和题目描述单调栈解法一代码演示单调栈解法二 单调栈专题 leetcode907. 子数组的最小值之和 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problems/sum-of-subarray-minimums…

如何快速学习一门计算机语言

如何快速学习一门计算机语言 掌握一门语言的基本数据类型和基本语法。掌握语言里数组和集合工具类的使用掌握循环分支控制掌握一下该计算机语言面向对象或者函数式编程的特征对异常或者错误的处理文件读写&#xff0c;输入输出流字符串的处理日志的打印运行时module或者librar…

【C语言基础】函数

C语言中的函数是模块化编程的基础&#xff0c;通过函数的定义、实参与形参的传递以及函数的调用流程&#xff0c;我们可以实现代码的重用和逻辑的封装。本文将深入探讨C语言函数的定义方式、实参与形参的传递机制&#xff0c;以及函数的调用流程和局部变量与栈内存的关系。 一、…

企业快递管理制定教程

在经济飞速发展的助力之下&#xff0c;现代企业接触到的制度越来越多&#xff0c;除了我们熟知的CRM、OA等等&#xff0c;管理制度进一步细分。企业寄件在企业内部运转中的地位越发重要&#xff0c;随之也产生了快递管理制度。不少人就会问&#xff1a;有必要这么细分吗&#x…

跨应用连接同一个redis,从redis取缓存,对象属性值都为null

本地idea部署和docker部署问题&#xff0c;连接同一个redis&#xff0c;idea项目的redis缓存&#xff0c;docker中取不到&#xff0c;docker中缓存的redis本地取不到 ✅ 原因&#xff1a;idea本地代码实体类未进行代码混淆&#xff0c;docker代码实体类进行了混淆&#xff0c;…

Caused by: java.io.IOException: CreateProcess error=206, 文件名或扩展名太长

java.io.IOException: Cannot run program "D:\javaAPP\jdk\bin\java.exe" (in directory "D:\java\demo"): CreateProcess error206, 文件名或扩展名太长。 Caused by: java.io.IOException: CreateProcess error206, 文件名或扩展名太长。 删除项目.ide…

Vue -- 生命周期 数据共享

1 组件的生命周期 1.1 生命周期 & 生命周期函数 生命周期&#xff08;Life Cycle&#xff09;是指一个组件从创建 -> 运行 -> 销毁的整个阶段&#xff0c;强调的是一个时间段。 生命周期函数&#xff1a;是由 vue 框架提供的内置函数&#xff0c;会伴随着组件的生命…