【保姆級教程】SpringBoot單元測試,文末介紹Postman的基本使用

來源:https://eamonyin.blog.csdn.net/
一、 單元測試的概念
概念:
1. 單元測試(unit testing),是指對軟件中的最小可測試單元進行檢查和驗證。在Java中單元測試的最小單元是類。
2. 單元測試是開發(fā)者編寫的一小段代碼,用于檢驗被測代碼的一個很小的、很明確的功能是否正確。執(zhí)行單元測試,就是為了證明這 段代碼的行為和我們期望是否一致。
單元測試引用:
1. 眾所周知,通過spring initialize創(chuàng)建的Spring Boot項目會在Maven中自動攜帶很多starter依賴:

其中包含了一個名為spring-boot-starter-test的依賴,本文是圍繞這個依賴展開。
2. Spring Boot中引入單元測試很簡單,添加如下依賴(即spring-boot-starter-test依賴):
<dependency><groupId>org.springframework.bootgroupId><artifactId>spring-boot-starter-testartifactId><scope>testscope>dependency>
3. spring-boot-starter-test有如下幾個庫:
spring-boot-starter-testUML圖:


二、單元測試的作用
在沒有接觸單元測試之前我們是怎么做測試的?一般有兩個方法:

在時間允許的情況下,編寫單元測試是程序員對代碼的自測,這是對自己代碼的負責。
寫單元測試的兩個動機:
保證或驗證實現功能。
保護已經實現的功能不被破壞。
三、Spring Boot引入的MockMvc的概念
1. 什么是Mock?
在面向對象的程序設計中,模擬對象(英語:mock object)是以可控的方式模擬真實對象行為的假對象。在編程過程中,通常通過模擬一些輸入數據,來驗證程序是否達到預期結果。
2. 為什么使用Mock對象?
使用模擬對象,可以模擬復雜的、真實的對象行為。如果在單元測試中無法使用真實對象,可采用模擬對象進行替代。
3. MockMvc的概念
MockMvc是由spring-test包提供,實現了對Http請求的模擬,能夠直接使用網絡的形式,轉換到Controller的調用,使得測試速度快、不依賴網絡環(huán)境。同時提供了一套驗證的工具,結果的驗證十分方便。
接口MockMvcBuilder,提供一個唯一的build方法,用來構造MockMvc。主要有兩個實現:StandaloneMockMvcBuilder和DefaultMockMvcBuilder。

4. MockMVC的基本步驟
(1) mockMvc.perform執(zhí)行一個請求。
(2) MockMvcRequestBuilders.get(“XXX”)構造一個請求。
(3) ResultActions.param添加請求傳值
(4) ResultActions.accept()設置返回類型
(5) ResultActions.andExpect添加執(zhí)行完成后的斷言。
(6) ResultActions.andDo添加一個結果處理器,表示要對結果做點什么事情,比如處使用print()輸出整個響應結果信息。
(7) ResultActions.andReturn表示執(zhí)行完成后返回相應的結果。
四、Service層的單元測試
第一步:Spring Boot中單元測試類寫在src/test/java目錄下,你可以手動創(chuàng)建具體測試類,也可以通過IDEA自動創(chuàng)建測試類,如下圖:(注:點選并打開相應代碼界面,再點擊菜單欄的Navigate)

第二步:按照第一步的方法,點擊測試后,出現圖一的對話框(如果想要測試的類已經存在測試類了會被列出來,也可以重新創(chuàng)建一個新的測試類),點擊”Create New Test…”會彈出圖二的對話框,可以選擇是否生成setUp以及要測試的成員方法等:
圖一
圖二
第三步:至此Service層的測試類就創(chuàng)建好了,測試類自動生成到了src/test/java目錄下項目的同級目錄中,如下圖:

Service層測試代碼如下:
(SpringRunner.class)public class XXXServiceTest {private XXXService XXXService;public void conflictTime() {DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");LocalDate start = LocalDate.parse("2020-10-26", dtf);LocalDate end = LocalDate.parse("2020-10-31", dtf);Integer integer = XXXService.ConflictTime("10000001", start, end);Assert.assertThat(integer, Matchers.notNullValue());//assertThat斷言后面介紹}}
注解解釋:
@SpringBootTest:獲取啟動類,加載配置,尋找主配置啟動類(被 @SpringBootApplication 注解的)?@RunWith(SpringRunner.class):讓JUnit運行Spring的測試環(huán)境,獲得Spring環(huán)境的上下文的支持
五、Controller層的單元測試
創(chuàng)建測試類步驟見第四部分,此處略。
第四部分只是針對Service層做了測試,但是咱么也需要對Controller層(API)做測試,這時候就用到MockMvc了,它使得你無需啟動項目工程就能測試這些接口。
MockMvc實現了對Http請求的模擬,能夠直接使用網絡的形式,轉換到Controller的調用,這樣可以使得測試速度快、不依賴網絡環(huán)境,而且提供了一套驗證的工具,這樣可以使得請求的驗證統(tǒng)一而且很方便。
Controller層部分的代碼將分為三個代碼塊講解,里面有看不懂的代碼先不要著急哦??,會在第五部分結尾處給大家匯總解答的,大家要堅持看到最后喲!??
代碼塊一:
public class DfTaskRecordControllerTest {private MockMvc mockMvc;public void setUp() throws Exception {System.out.println("---------------start---------------");save();get();System.out.println("================end================");????}
注解解釋:@SpringBootTest>:獲取啟動類,加載配置,尋找主配置啟動類(被 @SpringBootApplication 注解的)
@RunWith(SpringRunner.class)>:讓JUnit運行Spring的測試環(huán)境,獲得Spring環(huán)境的上下文的支持?@AutoConfigureMockMvc:用于自動配置MockMvc,配置后MockMvc類可以直接注入,相當于new MockMvc @Before:初始化方法 ,對于每一個測試方法都要執(zhí)行一次
代碼塊二:
()public void save() throws Exception {String json"{……}";//執(zhí)行一個RequestBuilder請求,會自動執(zhí)行SpringMVC的流程并映射到相應的控制器執(zhí)行處理;mockMvc.perform(MockMvcRequestBuilders.post("/XXX/save").content(json.getBytes()) //傳json參數.accept(MediaType.APPLICATION_JSON).contentType(MediaType.APPLICATION_JSON_VALUE).header("Authorization","Bearer ********-****-****-****-************")).andExpect(MockMvcResultMatchers.status().isOk()).andDo(print());????}
注解解釋:@Transactional:開啟事務功能
@Rollback(): 事務回滾,默認是true
代碼塊三:
public void get() throws Exception{ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get("/XXX/get").param("id", "**********").header("Authorization", "Bearer ********-****-****-****-************"));resultActions.andReturn().getResponse().setCharacterEncoding("UTF-8");resultActions.andExpect(MockMvcResultMatchers.status().isOk()).andDo(print());}}
/get運行結果如下:

現在將上面的一些瑣碎的知識點匯總一下:
mockMvc.perform:執(zhí)行一個請求MockMvcRequestBuilders.get(“/XXX/get”):構造一個請求,Post請求使用.post方法contentType(MediaType.APPLICATION_JSON_VALUE):代表發(fā)送端發(fā)送的數據格式是application/json;charset=UTF-8accept(MediaType.APPLICATION_JSON):代表客戶端希望接受的數據類型為application/json;charset=UTF-8header(“Authorization”,“Bearer XXXX”):代表在報文頭添加一些必須的信息,這里添加的是tokenResultActions.andExpect:添加執(zhí)行完成后的斷言ResultActions.andExpect(MockMvcResultMatchers.status().isOk()):方法看請求的狀態(tài)響應碼是否為200如果不是則拋異常,測試不通過ResultActions.andDo:添加一個結果處理器,表示要對結果做點什么事情,比如此處使用print():輸出整個響應結果信息
六、斷言的概念
斷言(assert),是編程術語,表示為一些布爾表達式,程序員相信在程序中的某個特定點該表達式值為真??梢栽谌魏螘r候啟用和禁用斷言驗證,因此可以在測試時啟用斷言而在部署時禁用斷言。
使用斷言是判斷一個函數或對象的一個方法所產生的結果是否符合你期望的那個結果。
七、新斷言assertThat使用
JUnit 4.4 結合 Hamcrest 提供了一個全新的斷言語法——assertThat。程序員可以只使用 assertThat 一個斷言語句,結合 Hamcrest 提供的匹配符,就可以表達全部的測試思想。
assertThat 的優(yōu)點:
優(yōu)點 1:以前 JUnit 提供了很多的 assertion 語句,如:assertEquals,assertNotSame,assertFalse,assertTrue,assertNotNull,assertNull 等,現在有了 JUnit 4.4,一條 assertThat 即可以替代所有的 assertion 語句,這樣可以在所有的單元測試中只使用一個斷言方法,使得編寫測試用例變得簡單,代碼風格變得統(tǒng)一,測試代碼也更容易維護。
優(yōu)點 2:assertThat 使用了 Hamcrest 的 Matcher 匹配符,用戶可以使用匹配符規(guī)定的匹配準則精確的指定一些想設定滿足的條件,具有很強的易讀性,而且使用起來更加靈活。
優(yōu)點 3:assertThat 不再像 assertEquals 那樣,使用比較難懂的“謂賓主”語法模式(如:assertEquals(3, x);),相反,assertThat 使用了類似于“主謂賓”的易讀語法模式(如:assertThat(x,is(3));),使得代碼更加直觀、易讀。
assertThat 的基本語法如下:
assertThat(?[value],?[matcher?statement]?);value?:接下來想要測試的變量值;?matcher statement?:使用 Hamcrest 匹配符來表達的對前面變量所期望的值的聲明,如果 value 值與 matcher statement 所表達的期望值相符,則測試成功,否則測試失敗。
八、Postman與Spring Boot 單元測試的區(qū)別
Spring Boot的單元測試主要針對方法層面,可以測試Service層這類非對外暴露的接口的類中方法,并且可一次性批量測試多個方法、支持事務回滾。
Postman針對接口進行http測試,我平時這個比較多,創(chuàng)建的測試接口可保存、分類。
九、Postman基本用法
Postman是一款功能強大的網頁調試與發(fā)送網頁HTTP請求的工具。Postman能夠發(fā)送任何類型的HTTP請求(GET, HEAD, POST,PUT..),附帶任何數量的參數和HTTP headers。支持不同的認證機制(basic, digest,OAuth),接收到的響應語法高亮(HTML,JSON或XML)。
安裝Postman?
官方網站:
https://www.getpostman.com/apps

安裝后,Postman是介樣嬸兒滴~~??

詳細的使用方法,在這里幫大家找到了一篇保姆級Postman使用教程:
https://www.cnblogs.com/okong/p/springboot-fifteen.html
