springboot企業級項目開發之項目測試——單元測試!

項目測試

項目測試是對項目的需求和功能進行測試,由測試人員寫出完整的測試用例,再按照測試用例執行測試。項目測試是項目質量的保證,項目測試質量直接決定了當前項目的交付質量。

測試人員在開展測試之前,首先需要進行測試的需求分析,測試需求分析包括:

測試內容:需要進行哪些方面的測試,包括功能測試、性能測試、可靠性測試、易用性測試和安全性測試等;

測試環境:測試環境的配置;

測試工具:選擇測試工具,包括缺陷管理工具和自動化測試工具等;

測試輪數:包括冒煙測試、功能測試、并發測試和弱網測試等。

測試需求分析完成后再開始項目測試。測試的步驟包括:冒煙測試、單元測試、集成測試、性能測試等,最后由產品經理完成產品的驗收。

單元測試

項目測試的第一步就是單元測試,單元測試也稱為模塊測試或組件測試。在項目開發過程中,單元測試用來檢查項目的單個單元或模塊是否正常工作,它是由開發人員在開發后立即在開發環境中完成的。

為什么要做單元測試

單元測試通常是軟件測試中基礎的測試類型,用于測試單獨模塊的功能是否有錯。它與功能測試的不同之處是,單元測試更加關注的是代碼內部的邏輯,而非功能的完整性。

根據上述描述,在項目中實施單元測試有以下5個目標:

隔離各部分代碼的功能;

確保單個模塊功能邏輯的正確性;

在開發的過程中及時發現代碼缺陷并修改;

發現產品開發早期邏輯中的Bug,以降低測試成本;

允許開發人員后續重構或升級代碼。

基于單元測試的目標,在項目中使用單元測試有以下4個優點:

能在產品開發周期的早期發現問題,可以大大地降低測試成本,因為早發現一個缺陷的成本要比晚期發現它的成本低得多。

在改變現有功能(回歸測試)的同時,可以減少缺陷。

簡化了調試過程(測試驅動開發就是基于測試用例來完成功能開發)。調試是在程序中發現并解決妨礙軟件正確運行缺陷的過程。當進行單元測試時,如果發現測試失敗,則只需要在調試代碼中做一下的更改,就可以快速定位錯誤。

進行單元測試,能夠保證代碼質量。

單元測試有哪些內容

單元測試的內容主要包括以下兩點:

單元測試的方法:通常使用白盒測試;

單元測試的類型:可以選擇手動測試或自動測試。

在對代碼進行單元測試時,可以使用手動的方式,也可以使用一些自動化工具。手動測試和自動化測試的區別主要體現在執行效率和操作等方面,如表7.1所示。

在實際開發中流行DevOps(Development+Operations)開發模式,因此建議讀者在項目中能使用自動化測試完成的任務盡量采用自動化測試來完成,以提升開發效率。

想要精通單元測試,還需要了解單元測試的幾個關鍵點:

(1)執行單元測試的時間:一般在開發完成后立即進行。

(2)誰做單元測試:開發人員進行自測。

(3)明確單元測試的具體任務,包括兩個方面:

首先,準備單元測試的計劃,包括:準備測試計劃;

回顧測試計劃;

修訂測試計劃;

定義單元測試計劃的基準數據。

其次,準備測試用例和腳本,包括:

準備測試環境、測試用例和腳本;

回顧測試用例和腳本;

修訂測試用例和腳本。

(4)定義單元測試用例和腳本的基準數據。

(5)執行單元測試,完成后出具單元測試報告。

常規的JUnit測試

JUnit是Java應用開發中使用最廣泛的單元測試框架。因為Java 8發布了Lambda表達式,使得Java的編碼風格發生了巨大的變化,所以JUnit團隊適時推出了新的框架——JUnit 5。JUnit 5能夠適應Lambda風格的編碼,建議在JDK 1.8及之后版本的項目中使用JUnit 5來創建和執行單元測試。本書中的單元測試以JUnit 5為例。

至于什么是JUnit,看以下官方的定義:

JUnit 5 is the next generation of JUnit. The goal is to create

an up-to-date foundation for developer-side testing on the JVM.

This includes focusing on Java 8 and above, as well as enabling

many different styles of testing.

官方提示JUnit 5是新一代的JUnit,它的目標是為JVM上的開發人員做測試創建一個最新的基礎,為Java 8及以上版本創建不同的測試風格。JUnit5框架=JUnit Platform+JUnit Jupiter+JUnit Vintage,其各部分框架的含義如下:

JUnit Platform是在JVM上啟動測試框架的基礎。

JUnit Jupiter是JUnit 5擴展的新的編程模型和擴展模型,用來編寫測試用例。Jupiter子項目為在平臺上運行Jupiter的測試提供了一個TestEngine(測試引擎)。

JUnit Vintage提供了一個在平臺上運行JUnit 3和JUnit 4的TestEngine。

JUnit 5的架構如圖7.1所示。

第一層測試用例:開發人員使用junit-jupiter-api等測試框架的API編寫業務代碼的單元測試。第二層測試引擎,JUnit測試框架實現引擎API的框架,jupiterengine和vintage- engine分別是JUnit 4和JUnit 5對測試引擎API的實現。

第三層junit-platform-engine:junit-platform-engine平臺引擎是對第二層中兩種不同引擎實現的抽象,是測試引擎的接口標準。

第四層IDEA:啟動器通過ServiceLoader發現測試引擎的實現并安排其執行。它為IDE和構建工具提供了API接口,因此在IDE中可以直接執行測試,例如,啟動測試并顯示其結果。

在項目中使用JUint 5進行單元測試時需要用到一些注解,如表7.2所示。此外,表中對JUnit 4和JUnit 5的注解使用進行了對比,供讀者參考。

根據以上的注解,下面使用JUint 5完成一個單元測試示例。

(1)新建一個項目,在pom.xml中添加JUnit 5的依賴,代碼如下:

<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>

<!--加入JUnit 5的版本測試;如果想用JUnit 4進行測試,把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>

</dependencies>

<build>

<plugins>

<plugin>

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

<artifactId>spring-boot-maven-plugin</artifactId>

</plugin>

</plugins>

</build>

(2)完成一些簡單的業務代碼。新建一個用戶服務類的接口

UserService:package com.example.junit5demo.service;

import java.util.IllegalFormatException;

/**

* 測試接口

*/

public interface UserService {

/**

* 登錄

* @param userName

* @param password

* @return

* @throws IllegalFormatException

*/

boolean login(String userName,String password) throws

IllegalFormat Exception;

/**

* 查詢數量

* @return

*/

int countNum();

}

(3)新建一個類來實現UserService接口,這里使用的是最簡單的實現方式,暫時先不連接數據庫。

package com.example.junit5demo.service;

/**

* 測試接口的實現

*/

import org.springframework.stereotype.Service;@Service

public class UserServiceImpl implements UserService {

@Override

public boolean login(String userName, String password) throws

Illegal

ArgumentException {

if (userName == null || password == null

|| userName.isEmpty() || password.isEmpty()) {

throw new IllegalArgumentException("不能為空");

}

if ("cc".equals(userName) && "123".equals(password)) {

return true;

}

return false;

}

@Override

public int countNum() {

return 18;

}

}

(4)實現UserService接口的方法后,在類名上右擊,依次選擇Go To |Test | Create New Test...命令,具體的過程如圖7.2和圖7.3所示。按照上述操作會跳轉到選擇測試方法的頁面,如圖7.4所示。選擇要測試的方法,選中寫的兩個方法,單擊OK按鈕就能自動生成測試類和要測試的方法。

(5)添加Spring Boot的啟動類,代碼如下:

package com.example.junit5demo;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication

public class Junit5DemoApplication {

public static void main(String[] args) {

SpringApplication.run(Junit5DemoApplication.class, args);

}

}

(6)修改自動生成的測試類代碼,完成兩個業務方法的單元測試工作。

完成后的代碼如下:

package com.example.junit5demo.service;

import lombok.extern.slf4j.Slf4j;

import org.junit.jupiter.api.*;

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

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

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

@Slf4j

@SpringBootTest //SpringBot測試類注解

class UserServiceImplTest {

//輸入要測試的類

@Autowired

private UserService userService;

//在所有測試方法之前執行

@BeforeAll

public static void beforeAll() {

log.info("before all");

}

//在每個測試方法執行之前執行

@BeforeEach

public void beforeEach() {

log.info("before each");

}

@AfterEach

public void afterEach() {

log.info("after each");

}

@AfterAll

public static void afterAll() {

log.info("after all");

} //測試countNum方法

@Test

void countNum() {

int i = userService.countNum();

assertEquals(18, i);

assertNotEquals(1, i);

}

// 測試login方法

@Test

void login() {

boolean cc1 = userService.login("cc", "123");

assertEquals(cc1, true);

boolean cc2 = userService.login("cc2", "123");

assertEquals(cc2, false);

assertThrows(IllegalArgumentException.class, () ->

userService.login("", "123"));

assertThrows(IllegalArgumentException.class, () ->

userService.login("123", null));

}

}

(7)運行這個測試類,在IDEA的控制臺打印結果如圖7.5所示。可以看到左側的兩個方法都顯示綠色的勾,說明已經通過測試用例。至此,我們已經完成了UserService類中所有方法的單元測試,可以看出,相關代碼邏輯正確。

提示:在完成單元測試后,如果開發人員在測試過程中優化了代碼,對自己的代碼進行了重構,則需要對重構后的代碼再次進行單元測試,以確保其邏輯的正確性,千萬不能忽略這一點。

Mock測試

Mock測試是指在單元測試的過程中對一些不容易構造的對象模擬一個對象進行使用的過程。一些對象只能在特定的環境中產生,例如HttpServletRequest對象必須從Servlet容器中才能構造出來,ResultSet對象必須依賴JDBC的實現才能構造,ProceedingJoinPoint對象的構建必須依賴AOP的實現。在遇到這種復雜對象的構建時,使用一個虛擬的對象(Mock對象)來替代,使用一個“假”的對象,便于在測試時順利檢測復雜對象(虛擬對象)的使用邏輯,以便快速、準確地測試自己的代碼邏輯。

Mock的出現是為了解決不同的單元之間由于耦合而難于開發與測試的問題,因此在單元測試和集成測試中都會用到Mock。Mock最大的作用是把單元測試的耦合分解開,如果你的代碼對另一個類或者接口有依賴,則可以排除依賴,只驗證所調用依賴的行為。例如,需要測試UserService中的方法,但是它依賴UserDao,這時就直接模擬一個用戶的數據庫對象,且只測試UserService中的方法,來驗證USerService中的邏輯正確與否。

在進行單元測試時,以下的幾個場景需要用到Mock對象:

需要將當前被測單元和依賴模塊分離,構造一個獨立的測試環境,不關注被測單元的依賴對象,而只關注被測單元的功能邏輯。例如,被測代碼中需要依賴第三方接口的返回值進行邏輯處理,可能因為網絡或者其他環境因素,調用第三方平臺經常會中斷或者失敗,而無法對被測單元進行測試,這時就可以使用Mock技術來將被測單元和依賴模塊獨立開,使得測試可以進行下去。

被測單元依賴的模塊尚未開發完成,而被測單元需要依賴模塊的返回值進行后續處理。包括前后端分離項目中,后端接口開發完成之前,前端接口需要測試;依賴的上游項目的接口尚未開發完成,需要接口聯調測試;service層的代碼包含對Dao層的調用,但是Dao層的代碼還沒完成,需要模擬Dao層的對象。

被測單元依賴的對象較難模擬或者構造比較復雜。例如,HttpServletRequest對象和數據庫的連接對象Connection都非常難以構造,則可以直接使用模擬后的對象。

在Java項目開發中有很多Mock框架,常見的有Mockito和PowerMock。

Mockito是一個在項目中最常用的優秀的單元測試Mock框架,它能滿足大部分業務的測試要求;PowerMock框架可以解決Mockito框架不能解決的更難的問題,如業務代碼中的靜態方法、私有方法和Final方法等。PowerMock框架是在EasyMock和Mockito的基礎上進行擴展的,它通過提供定制的類進行加載器并進行一些字節碼的修改,從而實現更強大的測試功能。

本書使用Java開發中常用的Mockito作為Mock框架。下面介紹如何在Spring Boot項目中使用Mock對象進行測試,從而完成單元測試。

(1)在7.1.3小節中的項目文件pom.xml中添加Mockito依賴,代碼如下:

<dependency>

<groupId>org.mockito</groupId>

<artifactId>mockito-core</artifactId>

<version>3.11.2</version>

</dependency>

(2)新建一個產品服務類接口ProductService及其實現類,代碼如下:

package com.example.junit5demo.service;

public interface ProductService {

int countNum(); boolean productExists(String name);

}

(3)新建上述ProductService接口的實現類,代碼如下:

package com.example.junit5demo.service;

import com.example.junit5demo.dao.ProductDao;

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

import org.springframework.stereotype.Service;

@Service

public class ProductServiceImpl implements ProductService {

@Autowired

private ProductDao productDao;

@Override

public int countNum() {

return productDao.countNum();

}

@Override

public boolean productExists(String name) {

if (name == null || name.isBlank()) {

return false;

}

return productDao.productExists(name);

}

}

(4)新建一個ProductDao類,直接使用類的實現返回數據,代碼如下:

package com.example.junit5demo.dao;

import org.springframework.stereotype.Repository;

import java.util.List;

@Repository

public class ProductDao {

public int countNum() {

return 2;

}

public boolean productExists(String name) {

/**

* 模擬Dao的方法

*/

List<String> apple = List.of("cc","apple", "orgage", "banana");

return apple.contains(name);

}

}

(5)生成ProductService的測試類,代碼如下:

package com.example.junit5demo.service;

import com.example.junit5demo.dao.ProductDao;

import org.junit.Assert;

import org.junit.jupiter.api.BeforeEach;

import org.junit.jupiter.api.Test;

import org.junit.jupiter.api.extension.ExtendWith;

import org.mockito.InjectMocks;

import org.mockito.Mock;

import org.mockito.MockitoAnnotations;

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

import org.springframework.test.context.junit.jupiter.SpringExtension;

import static org.mockito.Mockito.when;// 使用Spring的測試框架

@ExtendWith(SpringExtension.class)

@SpringBootTest

class ProductServiceImplTest {

/**

* 輸入要測試的對象

*/

@InjectMocks

ProductServiceImpl productService;

/**

* Mock對象的依賴對象

*/

@Mock

ProductDao productDao;

@BeforeEach

public void setUp() {

/**

* 初始化

*/

MockitoAnnotations.openMocks(this);

}

@Test

void coutNum() {

/**

* 當執行這個方法的時候直接返回5

*/

when(productDao.countNum()).thenReturn(5);

int num = productService.countNum();

/**

* 驗證返回值

*/

Assert.assertEquals(num,5);

}

@Test void productExists() {

/**

* 這里本來應該返回true,但是故意設置為false,再查看返回值

*/

when(productDao.productExists("cc")).thenReturn(false);

boolean cc = productService.productExists("cc");

Assert.assertEquals(cc,false);

}

@Test

void productExists3() {

when(productDao.productExists("apple")).thenReturn(false);

boolean cc = productService.productExists("apply");

Assert.assertEquals(cc,false);

}

}

(6)在本次測試用例中,需要測試ProductServiceImpl中的兩個業務方法。Product- ServiceImpl依賴ProductDao,這時模擬一個對象到測試對象中,當調用Dao的方法時就會返回設定的值,不會真正地執行Dao,而只測試ProductServiceImpl中的方法。執行本測試類ProductServiceImplTest中的所有測試方法,完成測試后的結果如圖7.6所示。可以看到,3個測試用例都已通過,說明已經完成了Mock單元測試。

以上就是使用Mock進行單元測試的過程。Mock測試是單元測試的一大利器,它能幫助開發人員更快地完成單元測試、業務代碼的檢測和Bug的修復。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/84896.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/84896.shtml
英文地址,請注明出處:http://en.pswp.cn/web/84896.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux kdump遠程轉存儲配置手冊教程

一、前言 kdump是一個Linux內核崩潰轉儲機制,當系統崩潰時,它可以捕獲內核的內存轉儲信息,幫助分析崩潰原因。將轉儲文件存儲到遠程位置,便于集中管理和分析。本教程將詳細介紹如何配置kdump將轉儲文件遠程轉存儲。 二、安裝kdump 在大多數Linux發行版中,kdump相關的工…

c++bind和forward完美轉化

前言 1. std::bind概述 std::bind是C11引入的功能模板&#xff0c;位于<functional>頭文件中&#xff0c;用于將函數、成員函數或函數對象與特定參數綁定&#xff0c;生成一個新的可調用對象。 1.1 基本用法 #include <iostream> #include <functional>v…

【Dify精講】第14章:部署架構與DevOps實踐【知識卡片】

第14章&#xff1a;部署架構與DevOps實踐http://www.airinto.com/share/49997bb7 一、Docker 容器化方案&#xff1a;從開發到生產的統一 二、Kubernetes 部署&#xff1a;走向云原生 三、CI/CD 流程設計&#xff1a;自動化的藝術 四、高可用架構&#xff1a;讓 AI 服務永不停歇…

el-cascader 設置可以手動輸入也可以下拉選擇

el-cascader 設置可以手動輸入也可以下拉選擇 稍微修改一下就可食用 <template slot"stationId" slot-scope""><div style"position: relative;"><!-- 可輸入也可顯示選項 --><el-input:value"stationNameInput"…

Unity Shader開發-著色器變體(1)-著色器變體概述

有時我們希望一份 Shader 源代碼可能滿足多種功能&#xff08;如處理法線貼圖、自發光、不同光照模式、陰影&#xff0c;支持GPUInstacing等多種功能&#xff09;。所以我們需要能夠實現Shader分支的方法。 一.Shader分支實現 主要有三種手段實現Shader分支&#xff1a; 1.靜…

ECK 簡化:在 GCP GKE Autopilot 上部署 Elasticsearch

作者&#xff1a;來自 Elastic Eduard Martin 學習如何使用 GKE Autopilot 和 ECK 在 GCP 上部署 Elasticsearch 集群。 想要獲得 Elastic 認證&#xff1f;了解下一次 Elasticsearch Engineer 培訓的時間&#xff01; Elasticsearch 擁有豐富的新功能&#xff0c;可以幫助你為…

測試一個軟件的性能有哪些指標?

在測試軟件性能時,通常會關注多個維度的指標,以評估系統在不同負載下的表現。以下是關鍵的性能測試指標分類和詳細說明: ?? 核心性能指標分類 1. 響應時間(Response Time) 定義:從發送請求到接收到響應所花費的時間 細分: 平均響應時間:所有請求的平均耗時 *P90/P95…

淺析std::atomic<T>::compare_exchange_weak和std::atomic<T>::compare_exchange_strong

目錄 std::atomic ::compare_exchange_weak 和 std::atomic ::compare_exchange_strong 核心原理 函數簽名 核心區別 典型用法 1. compare_exchange_weak&#xff08;循環內重試&#xff09; 2. compare_exchange_strong&#xff08;單次嘗試&#xff09; 底層機制 總…

舉出一個異步接口測試的例子

以下是一個完整的 ?異步接口測試? 實際案例&#xff0c;包含問題場景、解決方案、代碼實現和面試回答技巧&#xff0c;適合在面試中展示技術深度&#xff1a; ?案例背景? ?業務場景?&#xff1a; 測試一個AI圖片生成平臺的異步接口&#xff0c;用戶提交生成請求后&#…

更新麒麟連不上外網

問題&#xff1a;更新麒麟連不上外網 處理&#xff1a;本地建個下載地址 建立文件夾/root/x86.rpm&#xff0c;子文件夾&#xff1a;Packages、repodata&#xff0c;和在線站點建的一樣&#xff1a;Index of /NS/V10/V10SP1.1/os/adv/lic/base/x86_64/&#xff0c;然后就下載…

TensorFlow深度學習實戰——使用Hugging Face構建Transformer模型

TensorFlow深度學習實戰——使用Hugging Face構建Transformer模型 0. 前言1. 安裝 Hugging Face2. 文本生成3. 自動模型選擇和自動分詞4. 命名實體識別5. 摘要生成6. 模型微調相關鏈接 0. 前言 除了需要實現特定的自定義結構&#xff0c;或者想要了解 Transformer 工作原理外&…

SAP-ABAP:SAP全模塊的架構化解析,涵蓋核心功能、行業方案及技術平臺

一、核心業務模塊&#xff08;Logistics & Operations&#xff09; 模塊代號核心功能典型流程關鍵事務碼物料管理MM采購/庫存/發票校驗采購到付款 (P2P)ME21N&#xff08;采購訂單&#xff09;, MI31&#xff08;庫存盤點&#xff09;銷售與分銷SD訂單/定價/發貨/開票訂單…

實時預警!機場機坪井室無線智能液位監測系統助力安全降本

某沿海機場因地處多雨區域&#xff0c;每年雨季均面臨排水系統超負荷運行壓力。經勘測發現&#xff0c;5個井室因長期遭受地下水滲透侵蝕&#xff0c;井壁出現細微結構性裂縫&#xff0c;導致內部水位異常升高。作為機坪地下管網系統的核心節點&#xff0c;這些井室承擔著雨水導…

邊云協同 AI 視頻分析系統設計方案

目錄 一、項目背景與目標 二、系統架構概述 總體架構圖 三、ER 圖&#xff08;核心數據庫設計&#xff09; 實體關系圖簡述 數據表設計&#xff08;簡要&#xff09; 四、模型結構圖&#xff08;邊緣云端AI推理架構&#xff09; 邊緣模型&#xff08;YOLOv5-tiny/PP-YO…

vue3整合element-plus

為項目命名 選擇vue 框架 選擇TS 啟動測試&#xff1a; npm run dev 開始整合 element-plus npm install element-plus --save npm install unplugin-vue-components unplugin vitejs/plugin-vue --save-dev 修改main.ts import { createApp } from vue import ./style.cs…

【AI 測試】測試用例設計:人工智能語言大模型性能測試用例設計

目錄 一、性能測試可視化架構圖 &#xff08;1&#xff09;測試整體架構圖 &#xff08;2&#xff09;測試體系架構圖 &#xff08;3&#xff09;測試流程時序圖 二、性能測試架構總覽 &#xff08;1&#xff09;性能測試功能點 &#xff08;2&#xff09;測試環境要…

Windsurf SWE-1模型評析:軟件工程的AI革命

引言 軟件開發領域正經歷著前所未有的變革&#xff0c;AI輔助編程工具層出不窮&#xff0c;但大多數僅專注于代碼生成這一環節。Windsurf公司近期推出的SWE-1系列模型打破了這一局限&#xff0c;首次將AI應用擴展至軟件工程的全流程。這一舉措不僅反映了行業對AI工具認知的深化…

Qt for OpenHarmony 編譯鴻蒙調用的動態庫

簡介 Qt for Harmony? 是跨平臺開發框架 ?Qt? 與華為 ?OpenHarmony? 操作系統的深度集成方案&#xff0c;由 Qt Group 與華為聯合推動。其核心目標是為開發者提供一套高效工具鏈&#xff0c;實現 ??“一次開發&#xff0c;多端部署”?&#xff0c;加速 OpenHarmony 生…

退休時,按最低基數補繳醫療保險15年大概需要多少錢

在南京退休時&#xff0c;如果醫保繳費年限不足&#xff08;男需滿25年/女需滿20年&#xff09;&#xff0c;需補繳差額年限。若按最低基數一次性補繳15年醫保&#xff0c;費用估算如下&#xff08;以2024年政策為例&#xff09;&#xff1a; 一、補繳金額計算公式 總補繳費用…

wireshark過濾顯示rtmp協議

wireshark中抓包顯示的數據報文中&#xff0c;明明可以看到有 rtmp 協議的報文&#xff0c;但是過濾的時候卻顯示一條都沒有 查看選項中的配置&#xff0c;已經沒有 RTMP 這個協議了&#xff0c;已經被 RTMPT 替換了&#xff0c;過濾框中輸入 rtmpt 過濾即可