SpringBoot+JUnit5+MockMvc+Mockito單元測試的實現(xiàn)
今天聊聊如何在 SpringBoot 中集成 Junit5、MockMvc、Mocktio。Junit5 是在 Java 棧中應用最廣的測試框架,Junit4 一度霸榜。
升級到 Junit5 之后,除了增加 Java8 的很多特性,做了很多功能增強,在結構上做了優(yōu)化調整,拆分了很多不同的模塊,可以按需引入,比如:
- JUnit Platform - 在 JVM 上啟動測試框架
- JUnit Jupiter - 在 JUnit5 中編寫測試和擴展
- JUnit Vintage - 提供運行基于 JUnit3 和 JUnit4 的測試引擎
從 SpringBoot 2.2.0 之后,Junit5 已經成為了默認的 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 內容如下:
<?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 應用打包為可執(zhí)行 jar 的插件。
項目結構
因為是 DEMO 示例,我們實現(xiàn)一個 Echo 接口,能夠接收請求參數(shù),并返回加工后的字符串。按照慣例,我們使用萬能的Hello, World!。
我們的項目結構如下:
├── 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 應用啟動入口
- EchoController:接口定義
- EchoService:實現(xiàn)業(yè)務邏輯接口
- 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 接口的普通調用,代碼如下:
@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 應用的測試用例,然后通過AutoConfigureMockMvc啟動測試容器。這樣,就可以直接注入MockMvc實例測試 Controller 接口。
這里需要注意一點,網上很多教程會讓寫@ExtendWith({SpringExtension.class})這樣一個注解,其實完全沒有必要。通過源碼我們可以知道,SpringBootTest注解已經添加了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方法的攔截,使其返回我們定義好的響應結果。這種方式是為了在多系統(tǒng)或者多功能測試時,不需要真正調用接口。
比如,我們需要獲取用戶手機號,通常在接口中會校驗用戶有沒有登錄,我們就可以使用 Mockito 的能力代理登錄驗證,使結果永遠是 true。
到此這篇關于SpringBoot+JUnit5+MockMvc+Mockito單元測試的實現(xiàn)的文章就介紹到這了,更多相關SpringBoot JUnit5 MockMvc Mockito單元測試內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java在ElasticSearch中使用LocalDatetime類型
最近在開發(fā)一個搜索功能的需求的時候,遇到了LocalDatetime類型不能保存到ElasticSearch中的問題,這篇文章主要介紹了Java在ElasticSearch中使用LocalDatetime類型2023-10-10java源碼解析之String類的compareTo(String otherString)方法
這篇文章主要給大家介紹了關于java源碼解析之String類的compareTo(String otherString)方法的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學習學習吧2018-09-09java LRU(Least Recently Used )詳解及實例代碼
這篇文章主要介紹了java LRU(Least Recently Used )詳解及實例代碼的相關資料,Java里面實現(xiàn)LRU緩存通常有兩種選擇,一種是使用LinkedHashMap,一種是自己設計數(shù)據(jù)結構,使用鏈表+HashMap,需要的朋友可以參考下2016-11-11SpringBoot后端接口的實現(xiàn)(看這一篇就夠了)
這篇文章主要介紹了SpringBoot后端接口的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-09-09