集成测试

集成测试是指项目代码在单元测试完成后进行的第二阶段测试。集成测试的重点是在集成组件或单元之间交互时暴露缺陷,以保证不同模块之间相互调用的正确性。在Spring Boot的项目集成测试中,将测试Controller和Dao的完整请求处理。应用程序在服务器中运行,以创建应用程序上下文和所有的Bean,其中有些Bean可能会被覆盖以模拟某些行为。进行集成测试,是为了保证项目能够达到下面的目的:

降低项目中发生错误的风险;

验证接口的功能是否符合设计的初衷;

测试接口是否可用;

查找项目中的Bug并进行修复。

在项目开发中,需要开展集成测试的情况有以下4种:

单个模块由开发人员设计,而多个模块之间的设计可能不尽相同;

检查多个模块与数据库是否正确连通;

验证不同模块之间是否存在不兼容或错误的情况;

验证不同模块之间的异常和错误处理。

集成测试自动配置

Spring Boot框架支持集成测试,项目开发时只需要做简单的配置就可以完成集成测试。本节将在7.1节的基础上介绍项目配置后进行集成测试的过程。

首先在pom.xml中添加项目依赖:

<parent>

<groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId>

<version>2.3.10.RELEASE</version>

<relativePath/> <!-- lookup parent from repository -->

</parent>

<groupId>com.example</groupId>

<artifactId>junit5-demo</artifactId>

<version>0.0.1-SNAPSHOT</version>

<name>junit5-demo</name>

<description>Demo project for Spring Boot</description>

<properties>

<java.version>11</java.version>

</properties>

<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

<!--加入JUnit5进行测试;如果想用JUnit4进行测试,则把exclusions去除-->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-test</artifactId>

<scope>test</scope>

</dependency>

<dependency>

<groupId>org.projectlombok</groupId>

<artifactId>lombok</artifactId>

<optional>true</optional>

</dependency>

<dependency>

<groupId>org.mockito</groupId>

<artifactId>mockito-core</artifactId>

<version>3.11.2</version>

</dependency>

</dependencies>@SpringBootTest是Spring Boot提供的一个注解,表示当前类是SpringBoot环境中的一个测试类。如果使用的是JUnit 4,则需要用到@RunWith(SpringRunner.class)和@Spring-BootTest注解。但是在JUnit 5中,只需要使用@SpringBootTest注解就可以了。

测试Spring MVC入口

下面使用Spring中的集成测试模块来测试项目入口Controller的方法。

(1)新建GoodsController类,并新建要测试的业务代码,代码如下:

package com.example.junit5demo.controller;

import com.example.junit5demo.service.GoodsService;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.*;

@RestController

public class GoodsController {

@Autowired

private GoodsService goodsService;

@GetMapping("/queryGood")

public String queryGood(@RequestParam("name") String name) {

goodsService.queryGood(name);

return "queryGood " + name;

}

@PostMapping("/countGood")

public String countGood(@RequestBody Goods goods) {

goodsService.countGood(goods.getName());

return "countGood " + goods;

}

}

(2)新建Goods的实体类,代码如下:

package com.example.junit5demo.controller;

import lombok.Data;

@Data

public class Goods {

private long id;

private String name;

private int status;

}

(3)新建Goods的service和实现类,代码如下:

package com.example.junit5demo.service;

public interface GoodsService {

void queryGood(String name);

void countGood(String name);

}

Goods的实现类代码如下:

package com.example.junit5demo.service;

import org.springframework.stereotype.Service;

@Service

public class GoodsServiceImpl implements GoodsService {

@Override public void queryGood(String name) {

System.out.println("执行了goods的queryGood方法,参数:" + name);

}

@Override

public void countGood(String name) {

System.out.println("执行了goods的countGood方法,参数:" + name);

}

}

(4)编写Controller的集成测试用例,代码如下:

package com.example.junit5demo.controller;

import lombok.extern.SLF4J.SLF4J;

import org.junit.jupiter.api.BeforeEach;

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.test.autoconfigure.web.servlet.Auto

ConfigureMockMvc;

import org.springframework.boot.test.context.SpringBootTest;

import org.springframework.http.MediaType;

import org.springframework.mock.web.MockHttpSession;

import org.springframework.test.web.servlet.MockMvc;

import org.springframework.test.web.servlet.MvcResult;

import

org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

import

org.springframework.test.web.servlet.result.MockMvcResultHandlers;

import

org.springframework.test.web.servlet.result.MockMvcResultMatchers;

@Slf4j

@SpringBootTest

@AutoConfigureMockMvc

class GoodsControllerTest {

private MockHttpSession session; @Autowired

private MockMvc mvc;

@BeforeEach

public void setupMockMvc() {

//设置MVC

session = new MockHttpSession();

}

@Test

void queryGood() throws Exception {

MvcResult mvcResult = (MvcResult) mvc.perform(MockMvcRequest

Builders.get("/queryGood")

.accept(MediaType.ALL)

.session(session)

.param("name", "cc")

)

.andExpect(MockMvcResultMatchers.status().isOk())

.andDo(MockMvcResultHandlers.print())

.andReturn();

//得到返回代码

int status = mvcResult.getResponse().getStatus();

//得到返回结果

String result = mvcResult.getResponse().getContentAsString();

log.info("status是:{},内容是:{}", status, result);

}

@Test

void countGood() throws Exception {

String body = "{\"id\":1,\"name\":\"cc\",\"status\":2}";

MvcResult mvcResult = (MvcResult) mvc.perform(MockMvcRequest

Builders.post("/countGood")

.accept(MediaType.ALL)

.session(session)

.content(body)

.contentType(MediaType.APPLICATION_JSON)

)

.andExpect(MockMvcResultMatchers.status().isOk())

.andDo(MockMvcResultHandlers.print())

.andReturn(); //得到返回代码

int status = mvcResult.getResponse().getStatus();

//得到返回结果

String result = mvcResult.getResponse().getContentAsString();

log.info("status是:{},内容是:{}", status, result);

}

}

(5)运行第一个测试用例,在控制台上可以看到测试用例的输出结果,它执行了queryGood的GET方法,实际调用了代码中的方法,且返回了预期的结果。

执行了goods的queryGood方法,参数:cc

MockHttpServletRequest:

HTTP Method = GET

Request URI = /queryGood

Parameters = {name=[cc]}

Headers = [Accept:"*/*"]

Body = null

Session Attrs = {}

Handler:

Type = com.example.junit5demo.controller.GoodsController

Method = com.example.junit5demo.controller.GoodsController

#queryGood(String)

Async:

Async started = false

Async result = null

Resolved Exception:

Type = null

ModelAndView:

View name = null

View = null Model = null

FlashMap:

Attributes = null

MockHttpServletResponse:

Status = 200

Error message = null

Headers = [Content-Type:"text/plain;charset=UTF-8", Content

Length:"12"]

Content type = text/plain;charset=UTF-8

Body = queryGood cc

Forwarded URL = null

Redirected URL = null

Cookies = []

2021-07-10 15:51:30.786 INFO 15428 --- [ main]

c.e.j.controller.

GoodsControllerTest : status是:200,内容是:queryGood cc

2021-07-10 15:51:30.808 INFO 15428 --- [extShutdownHook]

o.s.s.concurrent.

ThreadPoolTaskExecutor : Shutting down ExecutorService 'application

TaskExecutor'

(6)执行第二个测试用例的方法,并执行countGood的POST方法,当前POST使用的是application/json方式,需要单独设置,通过日志可以看到已经请求成功。

执行了goods的countGood方法,参数:cc

MockHttpServletRequest:

HTTP Method = POST

Request URI = /countGood

Parameters = {}

Headers = [Content-Type:"application/json;charset=UTF-8",

Accept:"*/*", Content-Length:"31"]

Body = {"id":1,"name":"cc","status":2}

Session Attrs = {}Handler:

Type = com.example.junit5demo.controller.GoodsController

Method = com.example.junit5demo.controller.GoodsController#

countGood(Goods)

Async:

Async started = false

Async result = null

Resolved Exception:

Type = null

ModelAndView:

View name = null

View = null

Model = null

FlashMap:

Attributes = null

MockHttpServletResponse:

Status = 200

Error message = null

Headers = [Content-Type:"text/plain;charset=UTF-8", Content

Length:"40"]

Content type = text/plain;charset=UTF-8

Body = countGood Goods(id=1, name=cc, status=2)

Forwarded URL = null

Redirected URL = null

Cookies = []

2021-07-10 15:54:18.096 INFO 15720 --- [ main]

c.e.j.controller.

GoodsControllerTest : status是:200,内容是:countGood Goods(id=1,

name=cc, status=2)

2021-07-10 15:54:18.119 INFO 15720 --- [extShutdownHook]

o.s.s.concurrent.

ThreadPoolTaskExecutor : Shutting down ExecutorService 'application

TaskExecutor'

通过以上的集成测试,完成了API从入口开始的全链路方法调用,验证了所有的方法调用,并完成了业务代码的测试,至此完成了Controller的集成测试过程。

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTML 媒体(Media)

HTML 媒体&#xff08;Media&#xff09; 引言 HTML 媒体元素是构成现代网页的重要组成部分&#xff0c;它允许我们在网页中嵌入各种类型的媒体内容&#xff0c;如音频、视频、图像等。这些元素不仅丰富了网页的视觉效果&#xff0c;还提升了用户体验。本文将详细介绍 HTML 媒…

轻量化分布式AGI架构:基于区块链构建终端神经元节点的互联网智脑

一、架构概述 该架构通过将终端设备&#xff08;如手机、IoT设备&#xff09;转化为神经元节点&#xff0c;结合区块链技术构建去中心化智能网络&#xff0c;形成“互联网智脑”。其核心在于突破传统AGI算力瓶颈&#xff0c;实现数据安全共享与价值分配。 1.1 关键特征 分布…

【知识图谱构建系列6】:借了张显卡先跑着

文章目录 前情提要mistral模型运行代码前情提要 之前咱对LLM4KGC的代码稍作修改,目标是用modelscope来下载模型。 现在这个代码终于能跑了。 前面咱说,我们的显卡只有6G的显存。现在呢,我也成功借到了A100的显卡。这下,咱可以先跑跑这个项目默认带的mistral模型。 mist…

从零开始手写redis(16)实现渐进式 rehash map

手写 Redis 系列 java从零手写实现redis&#xff08;一&#xff09;如何实现固定大小的缓存&#xff1f; java从零手写实现redis&#xff08;三&#xff09;redis expire 过期原理 java从零手写实现redis&#xff08;三&#xff09;内存数据如何重启不丢失&#xff1f; jav…

List、Queue、Deque、Stack常用方法总结

Java 中几个常见的线性数据结构的 方法总结与对比&#xff0c;包括&#xff1a; List&#xff08;ArrayList、LinkedList&#xff09;Queue&#xff08;LinkedList、PriorityQueue&#xff09;Deque&#xff08;ArrayDeque、LinkedList&#xff09;Stack&#xff08;传统 Stac…

github为InfiniSynapse Docker提PR过程留档@Windows10

为InfiniSynapse Docker提了一个PR&#xff1a;修改阿里源为清华源&#xff0c;并不再安装PPA。 by skywalk163 Pull Request #1 chaozwn/infini_docker 整体操作 提PR的前置动作 先fork要提PR的项目git clone到本地用VSCode修改代码 提交PR git add . git commit -m &…

搭建加解密网站遇到的问题

本机向云服务器传输文件 用winscp 服务器在安装 SSH 服务时自动生成密钥对&#xff08;公钥私钥&#xff09; 为什么要有指纹验证&#xff1f; 防止中间人攻击&#xff08;Man-in-the-Middle&#xff09; 指纹验证打破这个攻击链&#xff1a; 小问题 安装python时 ./confi…

Docker高级管理--容器通信技术与数据持久化

第一节&#xff1a;容器通信技术 一&#xff1a;Docker 容器的网络模式 当项目大规模使用 Docker 时&#xff0c;容器通信的问题也就产生了。要解决容器通信问题&#xff0c;必须先了解很多关于网络的知识。Docker 的网络模式非常丰富&#xff0c;可以满足不同容器的通信要求&…

jsons.top工具之数组交集、去重

作为一名程序员&#xff0c;一款高效的 在线转换工具 &#xff08;在线时间戳转换 计算器 字节单位转换 json格式化&#xff09;必不可少&#xff01;https://jsons.top 用js实现一个轻量级的集合运算工具&#xff0c;可以对数组、集合去重、求交并差集&#xff0c;找出两个集…

Vue3 + Tailwind CSS 后台管理系统教程

Vue3 搭配 Tailwind CSS 是构建现代后台管理系统的绝佳组合。Vue3 提供了高效的响应式框架&#xff0c;而 Tailwind CSS 则让样式编写变得快速且灵活。下面我将分步骤教你如何创建一个功能完整的后台管理系统。 第 1 步&#xff1a;创建项目 首先&#xff0c;我们需要使用 Vit…

ComfyUI遭“Pickai“C++后门攻击,全球700余台AI图像生成服务器沦陷

大规模AI基础设施遭遇定向攻击 网络安全研究机构XLab近日发现针对ComfyUI框架的活跃攻击活动。ComfyUI是当前广泛用于部署大型AI图像生成模型的开源框架。攻击者通过该框架漏洞植入名为Pickai的C后门程序&#xff0c;已导致全球近700台服务器失陷。中国国家网络安全通报中心于…

Unity_VR_如何用键鼠模拟VR输入_PICO项目配置

文章目录 [TOC] 一、创建项目1.直接创建VR核心模板&#xff08;简单&#xff09;2.创建3D核心模板导入XR包&#xff08;并配置pico&#xff09;&#xff08;1&#xff09;创建项目&#xff08;2&#xff09;导入PICO的SDK&#xff08;3&#xff09;启用 PICO XR 插件&#xff0…

站点天下--网站在线和SSL过期监控的可靠助手

简介 网站突然访问不了、HTTPS证书到期&#xff0c;如果不能及时发现&#xff0c;将蒙受损失~ 站点天下提供应用在线状态监控和SSL证书到期监控&#xff1a; 若访问不了或SSL证书即将到期&#xff0c;则立即发邮件通知&#xff01;可以在线查看应用的在线状态和SSL证书到期时…

React setState原理

异步更新 原因 1设置为异步提升性能 如果setState每次调用直接执行&#xff0c;会造成 render 函数被频繁执行 &#xff0c;页面重新被渲染 解决&#xff1a;异步批处理 2如果render函数未执行时&#xff0c;保证props和state一致性 拿到最新state的方法 法一:setState&…

汉代大模型:历史镜像与智能重构的深度对话

引言&#xff1a;当历史遇见人工智能 一件汉代陶俑的三维模型正通过增强现实技术向观众演绎农耕场景。这个看似寻常的文物活化案例&#xff0c;实则蕴含着人工智能与历史学交叉领域的前沿探索——汉代大模型。作为连接过去与未来的智能载体&#xff0c;汉代大模型不仅重构了我…

es向量检索里的efSearchc参数是干嘛用的

在Elasticsearch的向量检索中&#xff0c;ef_search&#xff08;或efSearch&#xff09;是控制HNSW近似最近邻&#xff08;ANN&#xff09;搜索精度与性能平衡的关键参数&#xff0c;其作用机制和影响如下&#xff1a; &#x1f6e0;️ 一、核心作用 ef_search 限制底层图遍历…

Mac SSH终端操作工具 SecureCRT

SecureCRT Mac 是一款SSH终端工具&#xff0c;为计算专业人士提供高级会话管理工具。 也是一个功能强大且值得信赖的基于GUI的SHH和Telnet客户端&#xff0c;以及旨在提高工作效率并简化重复任务的终端仿真器。 借助SecureCRT mac版的帮助&#xff0c;您可以通过对ANSI&#…

UE5关卡快照

关卡快照&#xff08;Level Snapshots&#xff09; 使你能够在关卡的 世界大纲视图&#xff08;World Outliner&#xff09; 中保存 Actors 的特定配置&#xff0c;并立即将场景恢复到该状态。这样可以大幅简化复杂的设置&#xff0c;并避免对不同场景同一关卡的多个变体进行复…

Maven 或 Gradle 下载和添加 jar 文件的步骤

使用 Maven 或 Gradle 来自动下载和添加 jar 文件是管理 Java 项目依赖的最佳方式。 以下是如何使用 Maven 和 Gradle 来自动下载和添加 jar 文件的步骤&#xff1a; 使用 Maven # 创建一个 Maven 项目&#xff1a; mvn archetype:generate -DgroupIdcom.example -Dartifact…

JVM对象创建全流程解析

一、JVM对象创建流程 Ⅰ、类加载检查——JVM创建对象时先检查类是否加载 在虚拟机遇到new指令时&#xff0c;比如new关键字、对象克隆、对象序列化时&#xff0c;如下字节码 0: new #2 // class com/example/demo/Calculate检查指令的参数&#x…