SpringBoot+JUnit5+MockMvc+Mockito單元測試的實現(xiàn)
今天聊聊如何在 SpringBoot 中集成 Junit5、MockMvc、Mocktio。Junit5 是在 Java 棧中應(yīng)用最廣的測試框架,Junit4 一度霸榜。
升級到 Junit5 之后,除了增加 Java8 的很多特性,做了很多功能增強(qiáng),在結(jié)構(gòu)上做了優(yōu)化調(diào)整,拆分了很多不同的模塊,可以按需引入,比如:
- JUnit Platform - 在 JVM 上啟動測試框架
- JUnit Jupiter - 在 JUnit5 中編寫測試和擴(kuò)展
- JUnit Vintage - 提供運行基于 JUnit3 和 JUnit4 的測試引擎
從 SpringBoot 2.2.0 之后,Junit5 已經(jīng)成為了默認(rèn)的 Junit 版本。有了 JUnit Vintage,從 Junit4 遷移到 Junit5 的成本極低。所以本文就直接針對 Junit5 開始了。
版本
先說版本,是為了避免因為版本差異出現(xiàn)各種奇怪的問題:
- JDK:jdk8(小版本可以忽略)
- SpringBoot:2.5.2
- 繼承spring-boot-starter-parent
- 依賴spring-boot-starter-web
- 依賴spring-boot-starter-test
- JUnit:5.7.2
- Mockito:3.9.0
- hamcrest:2.2
SpringBoot 的好處在于,只要繼承spring-boot-starter-parent或引入spring-boot-pom-dependencies,然后添加spring-boot-starter-test依賴即可。定義的 POM 內(nèi)容如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.2</version>
</parent>
<groupId>cn.howardliu.effective.spring</groupId>
<artifactId>springboot-junit5-mockito</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-junit5-mockio</name>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
因為繼承了spring-boot-starter-parent,所以我們依賴的spring-boot-starter-test不需要寫具體的版本,可以直接集成父級的版本定義。其中,spring-boot-starter-web是用于提供 REST API 的 web 容器,spring-boot-starter-test可以提供各種測試框架的,spring-boot-maven-plugin是將 SpringBoot 應(yīng)用打包為可執(zhí)行 jar 的插件。
項目結(jié)構(gòu)
因為是 DEMO 示例,我們實現(xiàn)一個 Echo 接口,能夠接收請求參數(shù),并返回加工后的字符串。按照慣例,我們使用萬能的Hello, World!。
我們的項目結(jié)構(gòu)如下:
├── pom.xml
└── src
├── main
│ ├── java
│ │ └── cn
│ │ └── howardliu
│ │ └── effective
│ │ └── spring
│ │ └── springbootjunit5mockio
│ │ ├── SpringbootJunit5MockioApplication.java
│ │ ├── controller
│ │ │ └── EchoController.java
│ │ └── service
│ │ ├── EchoService.java
│ │ └── impl
│ │ └── EchoServiceImpl.java
│ └── resources
│ └── application.yaml
└── test
└── java
└── cn
└── howardliu
└── effective
└── spring
└── springbootjunit5mockio
└── controller
├── EchoControllerMockTest.java
└── EchoControllerNoMockitoTest.java
- SpringbootJunit5MockioApplication:SpringBoot 應(yīng)用啟動入口
- EchoController:接口定義
- EchoService:實現(xiàn)業(yè)務(wù)邏輯接口
- EchoServiceImpl:接口實現(xiàn)
- EchoControllerMockTest:使用 Mock 代理 EchoService 實現(xiàn)
- EchoControllerNoMockitoTest:直接測試接口實現(xiàn)
EchoServiceImpl
我們看下EchoService的實現(xiàn),這將是我們 DEMO 的核心實現(xiàn):
@Service
public class EchoServiceImpl implements EchoService {
@Override
public String echo(String foo) {
return "Hello, " + foo;
}
}
EchoControllerNoMockitoTest
我們先使用 Junit5+MockMvc 實現(xiàn) Controller 接口的普通調(diào)用,代碼如下:
@SpringBootTest(classes = SpringbootJunit5MockioApplication.class)
@AutoConfigureMockMvc
class EchoControllerNoMockitoTest {
@Autowired
private MockMvc mockMvc;
@Test
void echo() throws Exception {
final String result = mockMvc.perform(
MockMvcRequestBuilders.get("/echo/")
.param("name", "看山")
)
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print())
.andReturn()
.getResponse()
.getContentAsString(StandardCharsets.UTF_8);
Assertions.assertEquals("Hello, 看山", result);
}
}
我們通過SpringBootTest注解定義這是一個 SpringBoot 應(yīng)用的測試用例,然后通過AutoConfigureMockMvc啟動測試容器。這樣,就可以直接注入MockMvc實例測試 Controller 接口。
這里需要注意一點,網(wǎng)上很多教程會讓寫@ExtendWith({SpringExtension.class})這樣一個注解,其實完全沒有必要。通過源碼我們可以知道,SpringBootTest注解已經(jīng)添加了ExtendWith。
EchoControllerMockTest
這個測試用例中,我們通過 Mockito 組件代理EchoService的echo方法,代碼如下:
@SpringBootTest(classes = SpringbootJunit5MockioApplication.class)
@ExtendWith(MockitoExtension.class)
@AutoConfigureMockMvc
class EchoControllerMockTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private EchoService echoService;
@BeforeEach
void setUp() {
Mockito.when(echoService.echo(Mockito.any()))
.thenReturn("看山說:" + System.currentTimeMillis());
}
@Test
void echo() throws Exception {
final String result = mockMvc.perform(
MockMvcRequestBuilders.get("/echo/")
.param("name", "看山的小屋")
)
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print())
.andReturn()
.getResponse()
.getContentAsString(StandardCharsets.UTF_8);
Assertions.assertTrue(result.startsWith("看山"));
}
}
在這個示例中,我們需要注意@ExtendWith(MockitoExtension.class)注解,這個注解是用于引入MockBean的,我們通過對echo方法的攔截,使其返回我們定義好的響應(yīng)結(jié)果。這種方式是為了在多系統(tǒng)或者多功能測試時,不需要真正調(diào)用接口。
比如,我們需要獲取用戶手機(jī)號,通常在接口中會校驗用戶有沒有登錄,我們就可以使用 Mockito 的能力代理登錄驗證,使結(jié)果永遠(yuǎn)是 true。
到此這篇關(guān)于SpringBoot+JUnit5+MockMvc+Mockito單元測試的實現(xiàn)的文章就介紹到這了,更多相關(guān)SpringBoot JUnit5 MockMvc Mockito單元測試內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot使用定時器@Scheduled不管用的解決
這篇文章主要介紹了springboot使用定時器@Scheduled不管用的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12
SpringBoot中實現(xiàn)加載遠(yuǎn)程配置的代碼示例
本文章將通過結(jié)合consul config來講解在springboot中如何加載遠(yuǎn)程配置:通過consul config加載consul server中存儲的配置,需要的朋友可以參考下2023-06-06
Spring?Boot整合Zookeeper實現(xiàn)分布式鎖的場景分析
這篇文章主要介紹了Spring?Boot整合Zookeeper實現(xiàn)分布式鎖,zk實現(xiàn)分布式鎖完全是依靠zk節(jié)點類型當(dāng)中的臨時序號節(jié)點來實現(xiàn)的,本文通過實例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-06-06
SpringBoot和前端聯(lián)動實現(xiàn)存儲瀏覽記錄功能
這篇文章主要介紹了SpringBoot和前端聯(lián)動實現(xiàn)存儲瀏覽記錄功能,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2024-01-01
SpringBoot使用LibreOffice實現(xiàn)高保真Word轉(zhuǎn)PDF的方法
本文介紹了在SpringBoot中使用LibreOffce實現(xiàn)高保真Word轉(zhuǎn)PDF的方法,首先詳細(xì)說明了Windows、Mac、Linux系統(tǒng)及Docker環(huán)境下LibreOffice的安裝步驟和常見問題解決方案,需要的朋友可以參考下2026-02-02
Java業(yè)務(wù)中臺確保數(shù)據(jù)一致性的解決方案
數(shù)據(jù)一致性通常指關(guān)聯(lián)數(shù)據(jù)之間的邏輯關(guān)系是否正確和完整。而數(shù)據(jù)存儲的一致性模型則可以認(rèn)為是存儲系統(tǒng)和數(shù)據(jù)使用者之間的一種約定。如果使用者遵循這種約定,則可以得到系統(tǒng)所承諾的訪問結(jié)果2021-10-10

