springboot企業級項目開發之項目測試——集成測試!

集成測試

集成測試是指項目代碼在單元測試完成后進行的第二階段測試。集成測試的重點是在集成組件或單元之間交互時暴露缺陷,以保證不同模塊之間相互調用的正確性。在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…