Spring Boot 單元測試使用教程(僅供參考)

????????單元測試是軟件開發中至關重要的一環,Spring Boot 提供了強大的測試支持。以下是 Spring Boot 單元測試的詳細教程。


1. 準備工作

1.1 添加測試依賴

在?pom.xml?中添加測試相關依賴:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope>
</dependency><!-- 如果需要MockMvc -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><scope>test</scope>
</dependency><!-- 如果需要AssertJ -->
<dependency><groupId>org.assertj</groupId><artifactId>assertj-core</artifactId><version>3.24.2</version><scope>test</scope>
</dependency>

1.2 測試類基本結構

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
public class MyApplicationTests {@Testpublic void contextLoads() {// 測試Spring上下文是否正常加載}
}

2. 不同類型的測試

2.1 服務層測試

import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.junit.jupiter.api.extension.ExtendWith;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;@ExtendWith(MockitoExtension.class)
public class UserServiceTest {@Mockprivate UserRepository userRepository;@InjectMocksprivate UserService userService;@Testpublic void testGetUserById() {// 準備測試數據User mockUser = new User(1L, "test@example.com", "Test User");// 定義mock行為when(userRepository.findById(1L)).thenReturn(Optional.of(mockUser));// 調用測試方法User result = userService.getUserById(1L);// 驗證結果assertEquals("Test User", result.getName());verify(userRepository, times(1)).findById(1L);}
}

2.2 控制器層測試

使用MockMvc
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 static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;@SpringBootTest
@AutoConfigureMockMvc
public class UserControllerTest {@Autowiredprivate MockMvc mockMvc;@Testpublic void testGetUser() throws Exception {mockMvc.perform(get("/api/users/1")).andExpect(status().isOk()).andExpect(jsonPath("$.name").value("Test User"));}
}
使用WebTestClient (WebFlux)
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.reactive.server.WebTestClient;@SpringBootTest
@AutoConfigureWebTestClient
public class UserControllerWebTestClientTest {@Autowiredprivate WebTestClient webTestClient;@Testpublic void testGetUser() {webTestClient.get().uri("/api/users/1").exchange().expectStatus().isOk().expectBody().jsonPath("$.name").isEqualTo("Test User");}
}

2.3 數據庫測試

使用@DataJpaTest
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
import static org.assertj.core.api.Assertions.*;@DataJpaTest
public class UserRepositoryTest {@Autowiredprivate TestEntityManager entityManager;@Autowiredprivate UserRepository userRepository;@Testpublic void testFindByEmail() {// 準備測試數據User user = new User("test@example.com", "Test User");entityManager.persist(user);entityManager.flush();// 調用測試方法User found = userRepository.findByEmail(user.getEmail());// 驗證結果assertThat(found.getEmail()).isEqualTo(user.getEmail());}
}
使用@SpringBootTest + 測試數據庫
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.transaction.annotation.Transactional;
import static org.junit.jupiter.api.Assertions.*;@SpringBootTest
@ActiveProfiles("test")
@Transactional
public class UserServiceIntegrationTest {@Autowiredprivate UserService userService;@Autowiredprivate UserRepository userRepository;@Testpublic void testCreateUser() {User newUser = new User("new@example.com", "New User");User savedUser = userService.createUser(newUser);assertNotNull(savedUser.getId());assertEquals("New User", savedUser.getName());User found = userRepository.findById(savedUser.getId()).orElse(null);assertEquals("New User", found.getName());}
}

3. 常用測試技巧

3.1 參數化測試

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import static org.junit.jupiter.api.Assertions.assertTrue;public class ParameterizedTests {@ParameterizedTest@ValueSource(strings = {"racecar", "radar", "madam"})public void testPalindromes(String candidate) {assertTrue(StringUtils.isPalindrome(candidate));}
}

3.2 測試異常

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertThrows;public class ExceptionTest {@Testpublic void testException() {UserService userService = new UserService();assertThrows(UserNotFoundException.class, () -> {userService.getUserById(999L);});}
}

3.3 測試私有方法

雖然不推薦直接測試私有方法,但有時確實需要:

import org.junit.jupiter.api.Test;
import java.lang.reflect.Method;public class PrivateMethodTest {@Testpublic void testPrivateMethod() throws Exception {MyService service = new MyService();Method method = MyService.class.getDeclaredMethod("privateMethod", String.class);method.setAccessible(true);String result = (String) method.invoke(service, "input");assertEquals("expected", result);}
}

4. 測試配置

4.1 使用測試配置文件

創建?src/test/resources/application-test.properties

spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.h2.console.enabled=true

然后在測試類上使用:

@ActiveProfiles("test")

4.2 使用測試切片

Spring Boot 提供了多種測試切片注解:

  • @WebMvcTest?- 只測試MVC層

  • @DataJpaTest?- 只測試JPA組件

  • @JsonTest?- 只測試JSON序列化

  • @RestClientTest?- 只測試REST客戶端

    @WebMvcTest(UserController.class)
    public class UserControllerSliceTest {@Autowiredprivate MockMvc mockMvc;@MockBeanprivate UserService userService;@Testpublic void testGetUser() throws Exception {when(userService.getUserById(1L)).thenReturn(new User(1L, "test@example.com", "Test User"));mockMvc.perform(get("/api/users/1")).andExpect(status().isOk()).andExpect(jsonPath("$.name").value("Test User"));}
    }


5. 測試最佳實踐

  1. 命名規范:測試方法名應清晰表達測試意圖,如?shouldReturnUserWhenValidIdProvided()

  2. 單一職責:每個測試方法只測試一個功能點

  3. AAA模式:遵循Arrange-Act-Assert模式組織測試代碼

  4. 避免依賴:測試之間不應有依賴關系

  5. 快速反饋:保持測試快速執行,避免I/O操作

  6. 覆蓋率:追求合理的測試覆蓋率,但不要盲目追求100%

  7. Mock適度:不要過度使用mock,集成測試也很重要


6. 高級主題

6.1 自定義測試注解

import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;import java.lang.annotation.*;@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@SpringBootTest
@ActiveProfiles("test")
public @interface MyIntegrationTest {
}

然后可以在測試類上使用?@MyIntegrationTest?替代多個注解。

6.2 測試容器支持

使用Testcontainers進行集成測試:

import org.junit.jupiter.api.Test;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.boot.test.context.SpringBootTest;@Testcontainers
@SpringBootTest
public class UserRepositoryTestContainersTest {@Containerpublic static PostgreSQLContainer<?> postgreSQLContainer = new PostgreSQLContainer<>("postgres:13").withDatabaseName("testdb").withUsername("test").withPassword("test");@Testpublic void testWithRealDatabase() {// 測試代碼}
}

6.3 測試Spring Security

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.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;@SpringBootTest
@AutoConfigureMockMvc
public class SecuredControllerTest {@Autowiredprivate MockMvc mockMvc;@Test@WithMockUser(username="admin", roles={"ADMIN"})public void testAdminEndpoint() throws Exception {mockMvc.perform(get("/api/admin")).andExpect(status().isOk());}@Test@WithMockUser(username="user", roles={"USER"})public void testAdminEndpointForbidden() throws Exception {mockMvc.perform(get("/api/admin")).andExpect(status().isForbidden());}
}

7. 總結

Spring Boot 提供了全面的測試支持,從單元測試到集成測試,從Mock測試到真實環境測試。合理使用這些工具可以大大提高代碼質量和開發效率。

記住測試金字塔原則:多寫單元測試,適量集成測試,少量端到端測試。

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

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

相關文章

React Hooks速成

1、useReducer 適用情況為對一個狀態多種復雜操作,通俗的講就是比如對count這個變量加減乘除的各種情況 改造前 import { useState } from "react";function App() {//計數器const [count, setCount] useState(0);const handleIncrement () > {setCount(coun…

k8s node 內存碎片化如何優化?

在 Kubernetes 集群中&#xff0c;內存碎片化&#xff08;Memory Fragmentation&#xff09;會導致系統無法分配連續的內存塊&#xff0c;即使總內存充足&#xff0c;也可能觸發 OOM&#xff08;Out of Memory&#xff09;或影響性能。以下是針對 k8s Node 內存碎片化的優化策略…

目標檢測(Object Detection)研究方向常用數據集簡單介紹

目錄 一、目標檢測研究方向簡介 二、目標檢測常用數據集詳解 通用目標檢測數據集 領域專用數據集 三、數據集選擇建議 一、目標檢測研究方向簡介 目標檢測是計算機視覺的核心任務之一&#xff0c;旨在從圖像或視頻中定位并識別出所有感興趣的物體&#xff0c;輸出其類別和…

即開即用,封裝 Flask 項目為 exe 文件實操步驟

見字如面&#xff0c;朋友們&#xff01; 嗨&#xff0c;這里是 AIGC 創意人_竹相左邊&#xff01; 正如你們所知&#xff0c;我正在通過 AI 自學軟硬件工程師&#xff0c;目標是手搓一臺可回收火箭玩具&#xff01; 最近&#xff0c;我被《流浪地球 2》中馬兆的那句“沒有硬…

uniapp開發微信小程序時如何進行分包(新手圖文)

我們在進行uniapp微信小程序開發的時候&#xff0c;每次上傳都提示包太大&#xff0c;主包大小不能超過 2M&#xff0c; 這就很頭疼&#xff0c;這個時候&#xff0c;唯一的解決方案就是分包了&#xff0c;那如何進行分包呢&#xff1f; 分包步驟如下&#xff1a; 一、配置man…

基于C++的IOT網關和平臺2:github項目ctGateway技術說明書

初級代碼游戲的專欄介紹與文章目錄-CSDN博客 我的github:codetoys,所有代碼都將會位于ctfc庫中。已經放入庫中我會指出在庫中的位置。 這些代碼大部分以Linux為目標但部分代碼是純C++的,可以在任何平臺上使用。 源碼指引:github源碼指引_初級代碼游戲的博客-CSDN博客 系…

從巴別塔到通天塔:Manus AI 如何重構多語言手寫識別的智能版圖

一、引言&#xff1a;當人類手寫遇上 AI “巴別塔” 在幼發拉底河畔的古老傳說中&#xff0c;巴別塔的崩塌象征著人類語言互通的終結。而在數字時代&#xff0c;全球 7000 余種語言的手寫文字&#xff0c;正成為橫亙在人機交互之間的新 “巴別塔”—— 阿拉伯文的連筆天書、中…

n8n 快速入門2:構建自動化工作流

n8n 快速入門2:構建自動化工作流 什么是n8n?項目目標準備工作步驟一:創建新工作流步驟二:添加觸發節點步驟三:配置NASA節點與憑證1. 添加NASA節點2. 設置NASA API憑證3. 使用表達式設置時間范圍步驟四:添加If條件節點1. 創建條件分支2. 測試條件邏輯步驟五:配置輸出節點…

從實列中學習linux shell10 : 如何根據服務器的內存,cpu 以及 ssd硬盤 來確定mysql 的最大并發數

以下是根據服務器硬件資源智能推薦MySQL最大并發連接數 包含詳細的計算邏輯和實時資源檢測&#xff1a; 且記&#xff1a;該腳本要放在 安裝mysql的服務器上 運行 第一步&#xff1a;實現腳本 #!/bin/bash# 計算MySQL最大連接數推薦值 # 公式說明&#xff1a;取CPU計算值與內…

數據結構--AVL樹

目錄 前言 AVL樹的特點 AVL樹的插入 節點的定義 情況分析 AVL樹的旋轉 右單旋 左單旋 左右雙旋 右左雙旋 ?編輯總結 驗證AVL樹 前言 二叉搜索樹可以幫助我們以極高的效率查找(理想情況下是logn)&#xff0c;但是當在極端情況下&#xff0c;比如當樹中的節點值是有…

泰迪杯特等獎案例學習資料:基于多模態融合與邊緣計算的智能溫室環境調控系統

(第十二屆泰迪杯數據挖掘挑戰賽特等獎案例解析) 一、案例背景與核心挑戰 1.1 應用場景與行業痛點 在現代設施農業中,溫室環境調控直接影響作物產量與品質。傳統溫室管理存在以下問題: 環境參數耦合性高:溫度、濕度、光照、CO?濃度等參數相互影響,人工調控易顧此失彼。…

動手學深度學習12.1. 編譯器和解釋器-筆記練習(PyTorch)

以下內容為結合李沐老師的課程和教材補充的學習筆記&#xff0c;以及對課后練習的一些思考&#xff0c;自留回顧&#xff0c;也供同學之人交流參考。 本節課程地址&#xff1a;無 本節教材地址&#xff1a;12.1. 編譯器和解釋器 — 動手學深度學習 2.0.0 documentation 本節…

[java八股文][Java并發編程面試篇]并發安全

juc包下你常用的類&#xff1f; 線程池相關&#xff1a; ThreadPoolExecutor&#xff1a;最核心的線程池類&#xff0c;用于創建和管理線程池。通過它可以靈活地配置線程池的參數&#xff0c;如核心線程數、最大線程數、任務隊列等&#xff0c;以滿足不同的并發處理需求。Exe…

VMware搭建ubuntu保姆級教程

目錄 VMware Ubuntu 虛擬機配置指南 創建虛擬機 下載 Ubuntu ISO 新建虛擬機 網絡配置&#xff08;雙網卡模式&#xff09; 共享文件夾設置 SSH 遠程訪問配置 VMware Ubuntu 虛擬機配置指南 創建虛擬機 下載 Ubuntu ISO 【可添加我獲取】 官網&#xff1a;Get Ubunt…

馮諾依曼結構與哈佛架構深度解析

一、馮諾依曼結構&#xff08;Von Neumann Architecture&#xff09; 1.1 核心定義 由約翰馮諾依曼提出&#xff0c;程序指令與數據共享同一存儲空間和總線&#xff0c;通過分時復用實現存取。 存儲器總帶寬 指令帶寬 數據帶寬 即&#xff1a;B_mem f_clk W_data f_…

C/C++工程中的Plugin機制設計與Python實現

C/C工程中的Plugin機制設計與Python實現 1. Plugin機制設計概述 在C/C工程中實現Plugin機制通常需要以下幾個關鍵組件&#xff1a; Plugin接口定義&#xff1a;定義統一的接口規范動態加載機制&#xff1a;運行時加載動態庫注冊機制&#xff1a;Plugin向主程序注冊自己通信機…

node-sass安裝失敗解決方案

1、python環境問題 Error: Cant find Python executable "python", you can set the PYTHON env variable. 提示找不到python2.7版本&#xff0c; 方法一&#xff1a;可安裝一個python2.7或引用其他已安裝的python2.7 通過設置環境變量可以解決&#xff1b; 方法二&…

Netty高并發物聯網通信服務器實戰:協議優化與性能調優指南

目錄 1.總體設計 2.自定義協議設計(簡單版) 3.消息類型(1字節) 4.項目結構 5.核心功能代碼 (1)pom.xml(Maven依賴) (2)IotServer.java(服務器啟動器) (3)IotServerInitializer.java(Pipeline初始化) (4)DeviceChannelManager.java(設備連接管理器)…

多模態大語言模型arxiv論文略讀(六十)

Cantor: Inspiring Multimodal Chain-of-Thought of MLLM ?? 論文標題&#xff1a;Cantor: Inspiring Multimodal Chain-of-Thought of MLLM ?? 論文作者&#xff1a;Timin Gao, Peixian Chen, Mengdan Zhang, Chaoyou Fu, Yunhang Shen, Yan Zhang, Shengchuan Zhang, Xi…

面試常問系列(一)-神經網絡參數初始化-之自注意力機制為什么除以根號d而不是2*根號d或者3*根號d

首先先羅列幾個參考文章&#xff0c;大家之后可以去看看&#xff0c;加深理解&#xff1a; 面試常問系列(一)-神經網絡參數初始化面試常問系列(一)-神經網絡參數初始化之自注意力機制_注意力機制的參數初始化怎么做-CSDN博客面試常問系列(一)-神經網絡參數初始化-之-softmax-C…