文章目錄
一、 單元測試的概念
概念:
- 單元測試(unit testing),是指對軟件中的最小可測試單元進行檢查和驗證。在Java中單元測試的最小單元是類。
- 單元測試是開發者編寫的一小段代碼,用於檢驗被測代碼的一個很小的、很明確的功能是否正確。執行單元測試,就是爲了證明這 段代碼的行爲和我們期望是否一致。
單元測試引用:
- 衆所周知,通過
spring initialize
創建的Spring Boot項目會在Maven中自動攜帶很多starter依賴:
其中包含了一個名爲spring-boot-starter-test
的依賴,本文是圍繞這個依賴展開。
- Spring Boot中引入單元測試很簡單,添加如下依賴(即
spring-boot-starter-test
依賴):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
- spring-boot-starter-test有如下幾個庫:
spring-boot-starter-test
UML圖:
序號 | 庫名的解釋 |
---|---|
1 | JUnit 5:包含兼容 JUnit 4,Java 應用程序單元測試的事實標準 |
2 | Spring Test 和 SpringBootTest:對Spring Boot應用程序的公共和集成測試支持 |
3 | AssertJ:流式斷言庫 |
4 | Hamcrest:匹配對象庫 |
5 | Mockito:Java 模擬框架 |
6 | JSONassert:JSON 斷言庫 |
7 | JsonPath:JSON XPath |
二、單元測試的作用
在沒有接觸單元測試之前我們是怎麼做測試的?一般有兩個方法:
方法 | 弊端 |
---|---|
方法一:啓動整個應用,像用戶正常操作一樣。點擊界面按鈕,調用一個 API 等。 | 每次測試都要啓動整個項目 |
方法二:在代碼某個地方寫一個臨時入口,例如 java 的 main 方法,測試某個方法或者某個類。 | 入口用完要刪除,不然會影響項目的運行速度或效率 |
在時間允許的情況下,編寫單元測試是程序員對代碼的自測,這是對自己代碼的負責。
寫單元測試的兩個動機:
- 保證或驗證實現功能。
- 保護已經實現的功能不被破壞。
三、Spring Boot引入的MockMvc的概念
- 什麼是Mock?
在面向對象的程序設計中,模擬對象(英語:mock object)是以可控的方式模擬真實對象行爲的假對象。在編程過程中,通常通過模擬一些輸入數據,來驗證程序是否達到預期結果。
- 爲什麼使用Mock對象?
使用模擬對象,可以模擬複雜的、真實的對象行爲。如果在單元測試中無法使用真實對象,可採用模擬對象進行替代。
- MockMvc的概念
MockMvc是由spring-test包提供,實現了對Http請求的模擬,能夠直接使用網絡的形式,轉換到Controller的調用,使得測試速度快、不依賴網絡環境。同時提供了一套驗證的工具,結果的驗證十分方便。
接口MockMvcBuilder,提供一個唯一的build方法,用來構造MockMvc。主要有兩個實現:StandaloneMockMvcBuilder和DefaultMockMvcBuilder。
實例化方法 | 實例&解釋 |
---|---|
方法一 | mockMvc = MockMvcBuilders.standaloneSetup(new HelloWorldController()).build();通過參數指定一組控制器,這樣就不需要從上下文獲取了 |
方法二 | mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();指定WebApplicationContext,將會從該上下文獲取相應的控制器並得到相應的MockMvc |
- MockMVC的基本步驟
(1) mockMvc.perform執行一個請求。
(2) MockMvcRequestBuilders.get(“XXX”)構造一個請求。
(3) ResultActions.param添加請求傳值
(4) ResultActions.accept()設置返回類型
(5) ResultActions.andExpect添加執行完成後的斷言。
(6) ResultActions.andDo添加一個結果處理器,表示要對結果做點什麼事情,比如處使用print()輸出整個響應結果信息。
(7) ResultActions.andReturn表示執行完成後返回相應的結果。
四、Service層的單元測試
(以下圖片均引自文末 學習文章,因爲公司項目不方便截圖)第一步:Spring Boot中單元測試類寫在src/test/java目錄下,你可以手動創建具體測試類,也可以通過IDEA自動創建測試類,如下圖:(注:點選並打開相應代碼界面,再點擊菜單欄的Navigate) 第二步:按照第一步的方法,點擊測試後,出現 圖一的對話框(如果想要測試的類已經存在測試類了會被列出來,也可以重新創建一個新的測試類),點擊”Create New Test…”會彈出 圖二的對話框,可以選擇是否生成setUp以及要測試的成員方法等:
圖一
圖二
Service層測試代碼如下:
@SpringBootTest
@RunWith(SpringRunner.class)
public class XXXServiceTest {
@Resource
private XXXService XXXService;
@Test
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的測試環境,獲得Spring環境的上下文的支持
五、Controller層的單元測試
創建測試類步驟見第四部分,此處略。- 第四部分只是針對Service層做了測試,但是咱麼也需要對Controller層(API)做測試,這時候就用到MockMvc了,它使得你無需啓動項目工程就能測試這些接口。
- MockMvc實現了對Http請求的模擬,能夠直接使用網絡的形式,轉換到Controller的調用,這樣可以使得測試速度快、不依賴網絡環境,而且提供了一套驗證的工具,這樣可以使得請求的驗證統一而且很方便。
Controller層部分的代碼小名將分爲三個代碼塊講解,裏面有看不懂的代碼先不要着急哦😄,小名會在第五部分結尾處給大家彙總解答的,大家要堅持看到最後喲!😁
代碼塊一:
@SpringBootTest
@RunWith(SpringRunner.class)
@AutoConfigureMockMvc
public class DfTaskRecordControllerTest {
@Autowired
private MockMvc mockMvc;
@Before
public void setUp() throws Exception {
System.out.println("---------------start---------------");
save();
get();
System.out.println("================end================");
}
註解解釋:
@SpringBootTest
>:獲取啓動類,加載配置,尋找主配置啓動類(被 @SpringBootApplication 註解的)
@RunWith(SpringRunner.class)
>:讓JUnit運行Spring的測試環境,獲得Spring環境的上下文的支持
@AutoConfigureMockMvc
:用於自動配置MockMvc,配置後MockMvc類可以直接注入,相當於new MockMvc
@Before
:初始化方法 ,對於每一個測試方法都要執行一次
代碼塊二:
@Test
@Transactional
@Rollback()
public void save() throws Exception {
String json"{……}";
//執行一個RequestBuilder請求,會自動執行SpringMVC的流程並映射到相應的控制器執行處理;
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
代碼塊三:
@Test
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
:執行一個請求MockMvcRequestBuilders.get(“/XXX/get”)
:構造一個請求,Post請求使用.post方法contentType(MediaType.APPLICATION_JSON_VALUE)
:代表發送端發送的數據格式是application/json;charset=UTF-8accept(MediaType.APPLICATION_JSON)
:代表客戶端希望接受的數據類型爲application/json;charset=UTF-8header(“Authorization”,“Bearer XXXX”)
:代表在報文頭添加一些必須的信息,這裏添加的是tokenResultActions.andExpect
:添加執行完成後的斷言ResultActions.andExpect(MockMvcResultMatchers.status().isOk())
:方法看請求的狀態響應碼是否爲200如果不是則拋異常,測試不通過ResultActions.andDo
:添加一個結果處理器,表示要對結果做點什麼事情,比如此處使用print():輸出整個響應結果信息
六、斷言的概念
- 斷言(assert),是編程術語,表示爲一些布爾表達式,程序員相信在程序中的某個特定點該表達式值爲真。可以在任何時候啓用和禁用斷言驗證,因此可以在測試時啓用斷言而在部署時禁用斷言。
- 使用斷言是判斷一個函數或對象的一個方法所產生的結果是否符合你期望的那個結果。
七、新斷言assertThat使用
JUnit 4.4 結合 Hamcrest 提供了一個全新的斷言語法——assertThat。程序員可以只使用 assertThat 一個斷言語句,結合 Hamcrest 提供的匹配符,就可以表達全部的測試思想。assertThat 的優點:
優點 1:以前 JUnit 提供了很多的 assertion 語句,如:assertEquals,assertNotSame,assertFalse,assertTrue,assertNotNull,assertNull 等,現在有了 JUnit 4.4,一條 assertThat 即可以替代所有的 assertion 語句,這樣可以在所有的單元測試中只使用一個斷言方法,使得編寫測試用例變得簡單,代碼風格變得統一,測試代碼也更容易維護。
優點 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 單元測試的區別
- Spring Boot的單元測試主要針對方法層面,可以測試Service層這類非對外暴露的接口的類中方法,並且可一次性批量測試多個方法、支持事務回滾。
- Postman針對接口進行http測試,我平時這個比較多,創建的測試接口可保存、分類。
九、Postman基本用法
Postman是一款功能強大的網頁調試與發送網頁HTTP請求的工具。Postman能夠發送任何類型的HTTP請求(GET, HEAD, POST,PUT..),附帶任何數量的參數和HTTP headers。支持不同的認證機制(basic, digest,OAuth),接收到的響應語法高亮(HTML,JSON或XML)。安裝Postman 官方網站:https://www.getpostman.com/apps 安裝後,Postman是介樣嬸兒滴~~😊 詳細的使用方法,小名在這裏幫大家找到了一篇保姆級Postman使用教程,見文末 學習文章中的第二篇就可以啦~~😄
學習文章:
Spring Boot乾貨系列:(十二)Spring Boot使用單元測試
SpringBoot | 第十五章:基於Postman的RESTful接口測試