Java測試框架Mockito快速入門

Mockito結合TestNG快速入門

什么是Mockito

Mockito 是一個專門用于 Java 的強大測試框架,主要用來創建和管理模擬對象,輔助開發者進行單元測試,具有以下特點和功能:

  • 創建模擬對象:能通過簡潔的語法創建類或接口的模擬版本,這些模擬對象可作為真實對象的替代品,在調試期間使用,幫助隔離外部依賴。比如在測試一個依賴其他服務(如賬戶服務、數據庫訪問服務等)的業務邏輯時,可模擬這些外部服務,避免在測試中涉及真實的復雜操作(如真的修改數據庫數據、調用遠程接口等) 。
  • 定義行為:可以對模擬對象的方法進行 “樁(Stubbing)” 設置,即指定其返回值或讓其拋出異常。例如,使用when(...).thenReturn(...)來定義方法返回特定值;用thenThrow()模擬方法拋出異常,方便測試錯誤處理邏輯。
  • 驗證交互:提供驗證機制,通過verify(...)方法檢查模擬對象的方法是否按照預期被調用,以及調用的次數,從而驗證代碼與模擬對象之間的交互是否正確

引入的依賴

mockito-core

<!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
<dependency><groupId>org.mockito</groupId><artifactId>mockito-core</artifactId><version>5.15.2</version><scope>test</scope>
</dependency>

testng?

        <!-- https://mvnrepository.com/artifact/org.testng/testng --><dependency><groupId>org.testng</groupId><artifactId>testng</artifactId><version>7.11.0</version><scope>test</scope></dependency>

為什么需要mock

可以知道這個方法的調用情況,調用了多少次參數就是多少

給這個對象的行為做一個定義,來指定返回結果或者指定特定的動作

當使用mock對象時,如果不對其行為進行定義,則mock對象方法的返回值為返回類型的默認值


驗證和斷言

驗證:vertify()方法

驗證是校驗待驗證的對象是否發生過某些行為

package com.example.testng;import org.mockito.Mockito;
import org.testng.annotations.Test;import java.util.Random;public class MockitoDemoTest {@Testpublic void test(){//mock一個對象Random mock= Mockito.mock(Random.class);//輸出隨機數System.out.println(mock.nextInt());//驗證我們的mock對象是否用了nextInt()這個方法Mockito.verify(mock).nextInt();}
}

為什么我們的執行結果一直是0?

這是因為我們沒有給我們的mock出來的對象定義行為

斷言:Assert

判斷我們返回的結果是否符合我們的預期

package com.example.testng;import org.mockito.Mockito;
import org.testng.Assert;
import org.testng.annotations.Test;import java.util.Random;public class MockitoDemoTest {@Testpublic void test() {//mock一個對象Random mock = Mockito.mock(Random.class);Mockito.when(mock.nextInt()).thenReturn(100);Assert.assertEquals(100, mock.nextInt());}
}

符合預期,我們成功通過

不符合預期,我們測試失敗

package com.example.testng;import org.mockito.Mockito;
import org.testng.Assert;
import org.testng.annotations.Test;import java.util.Random;public class MockitoDemoTest {@Testpublic void test() {//mock一個對象Random mock = Mockito.mock(Random.class);Mockito.when(mock.nextInt()).thenReturn(100);Assert.assertEquals(101, mock.nextInt());}
}


給Mock對象進行打樁

打樁的意思其實就是對mock對象的行為進行定義

打樁的話是mockito里面的when()方法,定義我們的行為


@Mock注解

我們的mock注解必須搭配MockitoAnnotations.openMocks(testClass)方法一起使用

我們使用@Mock注解來Mock對象,而不是在代碼里面手動Mock我們的對象

package com.example.testng;import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.testng.Assert;
import org.testng.annotations.Test;import java.util.Random;public class MockitoDemoTest {@Mockprivate Random mock;@Testpublic void test() {MockitoAnnotations.openMocks(this);Mockito.when(mock.nextInt()).thenReturn(100);Assert.assertEquals(100, mock.nextInt());}
}

@BeforeTets與@AfterTest

package com.example.testng;import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.testng.Assert;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;import java.util.Random;public class MockitoDemoTest {@Mockprivate Random mock;@BeforeTestvoid setup() {System.out.println("測試前的準備");}@AfterTestvoid end() {System.out.println("測試結束");}@Testpublic void test() {MockitoAnnotations.openMocks(this);Mockito.when(mock.nextInt()).thenReturn(100);Assert.assertEquals(100, mock.nextInt());}
}


Spy方法與@Spy注解

spy方法與mock方法的不同是

1.被spy的對象會走真實的方法而mock對象不會

2.spy{}方法的參數是對象實例,mock的參數是class

package com.example.testng;import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.testng.Assert;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;import java.util.Random;public class MockitoDemoTest {@Spyprivate Random mock;@BeforeTestvoid setup() {MockitoAnnotations.openMocks(this);}@Testpublic void test() {Assert.assertEquals(100, mock.nextInt());}
}

我們沒有打樁,而且我們是Spy注解,所以我們不會輸出0,而是會去調用真正的Random方法

如果我們打樁了的話,那還是會按照我們打樁定義的規則來


打樁與Mock靜態方法

4個常見的打樁方法

thenCallRealMethod

thenReturn

thenThrow

thenAnswer

package com.example.testng;import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.testng.Assert;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;import java.util.Random;import static org.mockito.Mockito.when;public class MockitoDemoTest {@Spyprivate Random mock;@BeforeTestvoid setup() {MockitoAnnotations.openMocks(this);}@Testpublic void test() {//調用真實方法when(mock.nextInt()).thenCallRealMethod();//定義返回值when(mock.nextInt()).thenReturn(1);//定義返回什么錯誤when(mock.nextInt()).thenThrow(new RuntimeException());//自定義響應邏輯when(mock.nextInt()).thenAnswer(new Answer<Integer>() {@Overridepublic Integer answer(InvocationOnMock invocation) throws Throwable {// 這里可以編寫自定義的邏輯// invocation 包含了方法調用的信息,例如方法名、參數等// 這里簡單返回一個固定值 42return 42;}});}
}

Mock靜態方法

依賴

mockito-inline依賴包含了mockito-code依賴

注意我們使用mockito-inline依賴的時候要把mockito-code依賴注釋掉,我們不能同時引用

<!-- https://mvnrepository.com/artifact/org.mockito/mockito-inline -->
<dependency><groupId>org.mockito</groupId><artifactId>mockito-inline</artifactId><version>5.2.0</version><scope>test</scope>
</dependency>

在軟件開發的單元測試中,有時候我們需要對靜態方法進行模擬(Mock),這樣可以更好地控制測試環境、隔離依賴,提高測試的可維護性和穩定性。下面詳細介紹模擬靜態方法的相關內容,以 Java 語言結合 Mockito 框架為例


為什么需要 Mock 靜態方法
?

隔離依賴:靜態方法可能依賴于外部資源,如文件系統、數據庫等。在單元測試中,我們希望避免這些外部依賴的影響,通過模擬靜態方法可以將測試與外部資源隔離開來

控制返回值:靜態方法的返回值可能受到多種因素的影響,通過模擬靜態方法,我們可以精確控制其返回值,從而更方便地驗證業務邏輯


使用例子

我們這個類里面有個靜態方法

public class StaticUtils {public static int add(int a, int b) {return a + b;}
}

使用mockStatic

使用 try-with-resources語句確保 MockedStatic 對象在使用完畢后自動關閉,避免對后續測試產生影響

import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mockStatic;public class StaticUtilsTest {@Testpublic void testMockStaticMethod() {// 使用 try-with-resources 語句創建 MockedStatic 對象try (MockedStatic<StaticUtils> mockedStatic = mockStatic(StaticUtils.class)) {// 定義靜態方法的行為mockedStatic.when(() -> StaticUtils.add(2, 3)).thenReturn(10);// 調用靜態方法int result = StaticUtils.add(2, 3);// 驗證結果assertEquals(10, result);}}
}

單元測試如何提高我們的代碼覆蓋率

@InjectMocks注解

剩下的@mock和@spy注解修飾的對象會自動注入到被InjectMocks注解修飾的對象里面

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

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

相關文章

week 3 - More on Collections - Lecture 3

一、Motivation 1. Java支持哪種類型的一維數據結構&#xff1f; Java中用于在單一維度中存儲數據的數據結構&#xff0c;如arrays or ArrayLists. 2. 如何在Java下創建一維數據結構&#xff1f;&#xff08;1-dimensional data structure&#xff09; 定義和初始化這些一…

Ubuntu 防火墻iptables和 ufw

文章目錄 iptables 和 ufw 的區別Ubuntu 上使用 ufw 配置 iptables 和 ufw 的區別 iptables 和 ufw 是 Linux 系統中用于管理防火墻的工具&#xff0c;但它們的設計目標和使用方式有所不同。 iptables&#xff1a;功能強大&#xff0c;適合高級用戶和復雜場景&#xff0c;但配…

(動態規劃 最長連續遞增子序列)leetcode 674

我上個文章提到了最長遞增子序列這個題可以去看看 這個題目翻譯人話就是找出最長的遞增子串&#xff0c;用一層for循環就行&#xff0c;時間復雜度是O(n) 比起上個題&#xff0c;一個范圍多條子序列&#xff08;路徑&#xff09;這里一個范圍只有一條遞增路徑&#xff0c;所以…

STM32CubeMx DRV8833驅動

一、DRV8833驅動原理 ? STBY口接單片機的IO口&#xff0c;STBY置0電機全部停止&#xff0c;置1才能工作。STBY置1后通過AIN1、AIN2、BIN1、BIN2 來控制正反轉。 AIN1AIN2電機狀態00停止1speed反轉speed1正轉11停止 其中A端&#xff08;AIN1與AIN2&#xff09;只能控制AO1與…

JSON Schema 入門指南:如何定義和驗證 JSON 數據結構

文章目錄 一、引言二、什么是 JSON Schema&#xff1f;三、JSON Schema 的基本結構3.1 基本關鍵字3.2 對象屬性3.3 數組元素3.4 字符串約束3.5 數值約束 四、示例&#xff1a;定義一個簡單的 JSON Schema五、使用 JSON Schema 進行驗證六、實戰效果6.1 如何使用 七、總結 一、引…

前端Npm面試題及參考答案

目錄 npm 是什么?它的主要作用是什么? npm 包管理工具與 Yarn 有何不同? npm 的 package.json 文件有哪些重要字段? 什么是 npm 依賴?如何在項目中安裝、更新和移除依賴? npm 的 node_modules 目錄是什么?它的作用是什么? 什么是 npm 腳本?如何在 package.json 中…

零樣本思維鏈(Zero-shot CoT)

Large Language Models are Zero-Shot Reasoners (Kojima et al., 2022) 這篇文章研究了大型語言模型 (LLMs) 在推理任務上的能力&#xff0c;并提出了一種名為 Zero-shot-CoT 的新方法&#xff0c;該方法能夠有效地引導 LLM 進行多步驟推理&#xff0c;并在各種推理任務上取得…

day01_Java基礎

文章目錄 day01_Java基礎一、今日課程內容二、Java語言概述&#xff08;了解&#xff09;1、Java語言概述2、為什么要學習Java語言3、Java平臺版本說明4、Java特點 三、Java環境搭建&#xff08;操作&#xff09;1、JDK和JRE的概述2、JDK的下載和安裝3、IDEA的安裝4、IDEA的啟動…

設計模式 之 生產消費者模型 (C++)

文章目錄 設計模式 之 生產消費者模型 &#xff08;C&#xff09;引言生產消費者模型的基本概念為什么需要生產消費者模型應用場景&#xff1a;C 實現生產消費者模型代碼示例代碼詳細解釋共享資源和同步機制生產者函數 producer()消費者函數 consumer()主函數 main() 注意事項總…

Spring Boot 項目開發流程全解析

目錄 引言 一、開發環境準備 二、創建項目 三、項目結構 四、開發業務邏輯 1.創建實體類&#xff1a; 2.創建數據訪問層&#xff08;DAO&#xff09;&#xff1a; 3.創建服務層&#xff08;Service&#xff09;&#xff1a; 4.創建控制器層&#xff08;Controller&…

數據結構課程設計(java實現)---九宮格游戲,也稱幻方

【問題描述】 九宮格&#xff0c;一款數字游戲&#xff0c;起源于河圖洛書&#xff0c;與洛書是中國古代流傳下來的兩幅神秘圖案&#xff0c;歷來被認為是河洛文化的濫觴&#xff0c;中華文明的源頭&#xff0c;被譽為"宇宙魔方"。九宮格游戲對人們的思維鍛煉有著極大…

GPT-4.5 怎么樣?如何升級使用ChatGPTPlus/Pro? GPT-4.5設計目標是成為一款非推理型模型的巔峰之作

GPT-4.5 怎么樣&#xff1f;如何升級使用ChatGPTPlus/Pro? GPT-4.5設計目標是成為一款非推理型模型的巔峰之作 今天我們來說說上午發布的GPT-4.5&#xff0c;接下來我們說說GPT4.5到底如何&#xff0c;有哪些功能&#xff1f;有哪些性能提升&#xff1f;怎么快速使用到GPT-4.…

【vscode-解決方案】vscode 無法登錄遠程服務器的兩種解決辦法

解決方案一&#xff1a; 查找原因 命令 ps ajx | grep vscode 可能會看到一下這堆信息&#xff08;如果沒有大概率不是這個原因導致&#xff09; 這堆信息的含義&#xff1a;當你使用 vscode 遠程登錄服務器時&#xff0c;我們遠程機器服務端要給你啟動一個叫做 vscode serv…

一、對4*3按鍵模塊編程分析

一、4*3鍵盤模塊實物分析 說明&#xff1a; 1、橫著4排&#xff0c;豎著3列&#xff0c;加起來共7組&#xff0c;所以對外引出7根線。 2、根據排針終端引腳又可分兩類。即橫排和豎列對應的引腳。 二、代碼編寫構想&#xff1a; 1、使用7個gpio輸入中斷&#xff0c;檢測7個…

自然語言處理NLP入門 -- 第十節NLP 實戰項目 2: 簡單的聊天機器人

一、為什么要做聊天機器人&#xff1f; 在互聯網時代&#xff0c;我們日常接觸到的“在線客服”“自動問答”等&#xff0c;大多是以聊天機器人的形式出現。它能幫我們快速回復常見問題&#xff0c;讓用戶獲得及時的幫助&#xff0c;并在一定程度上減少人工客服的壓力。 同時&…

linux(1)文件管理

文章目錄 文件目錄系統相對路徑絕對路徑命令解析器文件管理 文件目錄系統 bin&#xff1a; 二進制文件目錄&#xff0c;存儲可執行文件 dev&#xff1a;設備目錄&#xff0c;所有的硬件都會抽象成文件存儲&#xff0c;比如鼠標鍵盤 home&#xff1a;存儲普通用戶的家目錄 li…

CSS—選擇器詳解:5分鐘動手掌握選擇器

個人博客&#xff1a;haichenyi.com。感謝關注 1. 目錄 1–目錄2–引言3–種類4–優先級 引言 什么是選擇器&#xff1f; CSS選擇器是CSS&#xff08;層疊樣式表&#xff09;中的一種規則&#xff0c;用于指定要應用樣式的HTML元素。它們就像是指向網頁中特定元素的指針&#…

大模型微調入門(Transformers + Pytorch)

目標 輸入&#xff1a;你是誰&#xff1f; 輸出&#xff1a;我們預訓練的名字。 訓練 為了性能好下載小參數模型&#xff0c;普通機器都能運行。 下載模型 # 方式1&#xff1a;使用魔搭社區SDK 下載 # down_deepseek.py from modelscope import snapshot_download model_…

DeepSeek實戰

DeepSeek 接入實戰&#xff1a;從零開始快速上手 引言 在當今的 AI 領域&#xff0c;DeepSeek 作為一個強大的自然語言處理&#xff08;NLP&#xff09;平臺&#xff0c;提供了豐富的 API 接口&#xff0c;幫助開發者快速實現智能對話、文本生成、語義分析等功能。本文將帶你…

Android NDK打包封裝教程與優化技巧

關于NDK打包封裝的問題。首先,用戶可能不太清楚NDK的基本概念,所以我應該先解釋NDK是什么以及它的作用。然后,用戶可能想知道如何在Android項目中使用NDK,所以需要分步驟說明配置過程,包括安裝NDK、配置CMake或ndk-build,創建JNI接口,編寫C/C++代碼,編譯和打包。 接下…