Junit5在IDEA中快速使用詳解
一、POM引用
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>有些框架引用后可能會顯示junit3,不會切換到5
右側(cè) Maven 面板 → 點擊:
Reload All Maven Projects
等依賴下載完。
如果還是不行,執(zhí)行:
File → Invalidate Caches / Restart
然后重啟 IDEA。
二、快速生成測試類
創(chuàng)建測試類的方式是:
光標(biāo)放在類名上 → 快捷鍵生成測試
1、打開你要測試的類
例如:CalcService.java
2、光標(biāo)放在類名上
public class CalcService {
3、按快捷鍵
- Windows / Linux:
- Ctrl + Shift + T
- macOS:
- ? + Shift + T
4、選擇
Create New Test...

三、彈窗選項

1、Testing library
JUnit5
- 是干嘛的?
- 選擇測試框架版本。
- 該怎么選?
- 永遠(yuǎn)選 JUnit5
- 不用碰 3 / 4。
2、Class name
EwisePReportControllerTest
- 是干嘛的?
- 生成的測試類名稱。
- 建議:
- 保持默認(rèn):原類名 + Test
3、Superclass
- 現(xiàn)在是空的(這是對的)。
- 是干嘛的?
- 老版本 JUnit3 需要繼承:
extends TestCase
- JUnit5 需要嗎?
- 完全不需要。
- 結(jié)論:
- 保持為空。
4、Destination package
com.ruoyi.report.controller
- 是干嘛的?
- 測試類放在哪個包。
- 正確規(guī)則:
- 必須和被測類包路徑一致。
比如:
src/main/java/com/ruoyi/report/controller
測試必須在:
src/test/java/com/ruoyi/report/controller
IDEA 默認(rèn)幫你處理好了,不用改。
5、Generate → setUp / tearDown
- 是干嘛的?
- 老式初始化方法。
- 對應(yīng):
@BeforeEach @AfterEach
- 要不要勾?
- 90% 情況:
- 不勾。
- 你以后真需要再自己寫。
6、Show inherited methods
- 是干嘛的?
- 顯示父類方法(比如 BaseController 的方法)。
- 要不要勾?
- 不用。
- Controller 測試不測父類。
7、Generate test methods for(最容易誤解的)
下面一堆:
list() getInfo() add() edit() remove() ...
是干嘛的?
幫你生成“空測試方法”:
@Test
void list() {
}
只是生成一個殼子。
要不要勾?
建議:
- Controller:不要全勾
- Service:也別亂勾
- 只勾你馬上要寫的那一個
否則會變成:
@Test void list(){}
@Test void getInfo(){}
@Test void add(){}
...
四、若依 Controller 標(biāo)準(zhǔn)測試模板
假設(shè)你的 Controller 是:
@RequestMapping("/report")
@RestController
public class EwisePReportController {
標(biāo)準(zhǔn)測試類(推薦寫法)
package com.ruoyi.report.controller;
import com.ruoyi.RuoYiApplication;
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(classes = RuoYiApplication.class)
@AutoConfigureMockMvc
class EwisePReportControllerTest {
@Autowired
private MockMvc mockMvc;
/**
* 測試列表接口(返回 TableDataInfo)
*/
@Test
void list_shouldReturnSuccess() throws Exception {
mockMvc.perform(get("/report/list"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.total").exists())
.andExpect(jsonPath("$.rows").exists());
}
/**
* 測試詳情接口(返回 AjaxResult)
*/
@Test
void getInfo_shouldReturnAjaxResult() throws Exception {
mockMvc.perform(get("/report/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").exists())
.andExpect(jsonPath("$.msg").exists());
}
/**
* 測試新增接口(POST)
*/
@Test
void add_shouldReturnSuccess() throws Exception {
String json = """
{
"name": "測試報表",
"remark": "測試數(shù)據(jù)"
}
""";
mockMvc.perform(post("/report")
.contentType("application/json")
.content(json))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(200));
}
}
如果你開啟了 Spring Security(若依默認(rèn)開啟)
如果接口被權(quán)限攔截,會 401 或 403。
解決方式:
方法一(簡單粗暴測試)
@SpringBootTest(classes = RuoYiApplication.class) @AutoConfigureMockMvc(addFilters = false)
addFilters = false = 關(guān)閉安全過濾器(測試環(huán)境用)
方法二(更規(guī)范)
加:
@WithMockUser
例如:
@Test
@WithMockUser(username = "admin")
void list_shouldReturnSuccess() throws Exception {
需要引入:
import org.springframework.security.test.context.support.WithMockUser;
若依三種常見返回結(jié)構(gòu)斷言寫法
1、AjaxResult 結(jié)構(gòu)
若依標(biāo)準(zhǔn)結(jié)構(gòu):
{
"code": 200,
"msg": "操作成功",
"data": {}
}
斷言寫法:
.andExpect(jsonPath("$.code").value(200))
.andExpect(jsonPath("$.msg").exists())
2、TableDataInfo 結(jié)構(gòu)
{
"total": 10,
"rows": [...]
}
斷言:
.andExpect(jsonPath("$.total").isNumber())
.andExpect(jsonPath("$.rows").isArray())
3、導(dǎo)出接口(Excel)
@Test
void export_shouldReturnFile() throws Exception {
mockMvc.perform(post("/report/export"))
.andExpect(status().isOk())
.andExpect(header().exists("Content-Disposition"));
}
五、若依Service標(biāo)準(zhǔn)測試模板(重點)
典型若依 Service 結(jié)構(gòu)
@Service
public class EwisePReportServiceImpl implements IEwisePReportService {
@Autowired
private EwisePReportMapper reportMapper;
@Override
public List<EwisePReport> selectEwisePReportList(EwisePReport report) {
return reportMapper.selectEwisePReportList(report);
}
@Override
public int insertEwisePReport(EwisePReport report) {
report.setCreateTime(new Date());
return reportMapper.insertEwisePReport(report);
}
}
標(biāo)準(zhǔn)寫法 1:純單元測試
- 不啟動 Spring
- 不訪問數(shù)據(jù)庫
- 用 Mockito 模擬 mappe
模板
package com.ruoyi.report.service;
import com.ruoyi.report.domain.EwisePReport;
import com.ruoyi.report.mapper.EwisePReportMapper;
import com.ruoyi.report.service.impl.EwisePReportServiceImpl;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class EwisePReportServiceTest {
@Mock
private EwisePReportMapper reportMapper;
@InjectMocks
private EwisePReportServiceImpl reportService;
/**
* 測試查詢列表
*/
@Test
void selectList_shouldReturnData() {
EwisePReport query = new EwisePReport();
when(reportMapper.selectEwisePReportList(query))
.thenReturn(List.of(new EwisePReport()));
List<EwisePReport> result =
reportService.selectEwisePReportList(query);
assertNotNull(result);
assertEquals(1, result.size());
verify(reportMapper, times(1))
.selectEwisePReportList(query);
}
/**
* 測試新增時是否自動設(shè)置時間
*/
@Test
void insert_shouldSetCreateTime() {
EwisePReport report = new EwisePReport();
when(reportMapper.insertEwisePReport(report))
.thenReturn(1);
int rows = reportService.insertEwisePReport(report);
assertEquals(1, rows);
assertNotNull(report.getCreateTime());
verify(reportMapper, times(1))
.insertEwisePReport(report);
}
}
寫復(fù)雜邏輯時的測試模板
如果你有這種邏輯:
public int calcDiff(Integer first, Integer last) {
if (first == null || last == null) {
return 0;
}
return last - first;
}
測試寫法:
@Test
void calcDiff_normal() {
int result = reportService.calcDiff(3, 10);
assertEquals(7, result);
}
@Test
void calcDiff_null() {
int result = reportService.calcDiff(null, 10);
assertEquals(0, result);
}
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot異步Async使用Future與CompletableFuture區(qū)別小結(jié)
本文主要介紹了SpringBoot異步Async使用Future與CompletableFuture區(qū)別小結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06
Java中的深拷貝(深復(fù)制)和淺拷貝(淺復(fù)制)介紹
這篇文章主要介紹了Java中的深拷貝(深復(fù)制)和淺拷貝(淺復(fù)制)介紹,需要的朋友可以參考下2015-03-03
SpringBoot快速設(shè)置攔截器并實現(xiàn)權(quán)限驗證的方法
本篇文章主要介紹了SpringBoot快速設(shè)置攔截器并實現(xiàn)權(quán)限驗證的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-01-01
Java如何通過"枚舉的枚舉"表示二級分類的業(yè)務(wù)場景
這篇文章主要介紹了Java如何通過"枚舉的枚舉"表示二級分類的業(yè)務(wù)場景問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-06-06
spring boot異步(Async)任務(wù)調(diào)度實現(xiàn)方法
在沒有使用spring boot之前,我們的做法是在配置文件中定義一個任務(wù)池,然后將@Async注解的任務(wù)丟到任務(wù)池中去執(zhí)行,那么在spring boot中,怎么來實現(xiàn)異步任務(wù)的調(diào)用了,下面通過本文給大家講解,需要的朋友參考下2018-02-02
Java 中二進(jìn)制轉(zhuǎn)換成十六進(jìn)制的兩種實現(xiàn)方法
這篇文章主要介紹了Java 中二進(jìn)制轉(zhuǎn)換成十六進(jìn)制的兩種實現(xiàn)方法的相關(guān)資料,需要的朋友可以參考下2017-06-06
Jackson java動態(tài)去除返回json中的值方式
文章介紹了在Java中使用@JsonInclude注解動態(tài)去除返回JSON中的非必需字段(如分頁信息)的解決方案,通過在字段上添加@JsonInclude注解并選擇合適的策略(如NON_NULL或NON_EMPTY),可以在非分頁情況下取消分頁字段,從而提高返回結(jié)果的靈活性和效率2024-12-12
Mybatis批量插入insert的三種實現(xiàn)方式
本文介紹了在Oracle和MyBatis中進(jìn)行批量插入的不同方式,包括Oracle的INSERT ALL和SELECT FROM DUAL方法,以及MyBatis的UNION ALL方法,并提醒讀者這些是個人經(jīng)驗總結(jié)2026-03-03

