Spring Boot 單元測(cè)試

一、 單元測(cè)試的概念
概念:
單元測(cè)試引用:
1. 眾所周知,通過spring initialize創(chuàng)建的Spring Boot項(xiàng)目會(huì)在Maven中自動(dòng)攜帶很多starter依賴:

其中包含了一個(gè)名為spring-boot-starter-test的依賴,本文是圍繞這個(gè)依賴展開。
spring-boot-starter-test依賴):<dependency>
? <groupId>org.springframework.bootgroupId>
? <artifactId>spring-boot-starter-testartifactId>
? <scope>testscope>
dependency>3. spring-boot-starter-test有如下幾個(gè)庫:
spring-boot-starter-testUML圖:


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

在時(shí)間允許的情況下,編寫單元測(cè)試是程序員對(duì)代碼的自測(cè),這是對(duì)自己代碼的負(fù)責(zé)。
寫單元測(cè)試的兩個(gè)動(dòng)機(jī):
1. 保證或驗(yàn)證實(shí)現(xiàn)功能。
2. 保護(hù)已經(jīng)實(shí)現(xiàn)的功能不被破壞。
三、Spring Boot引入的MockMvc的概念
1. 什么是Mock?

(2) MockMvcRequestBuilders.get(“XXX”)構(gòu)造一個(gè)請(qǐng)求。
(3) ResultActions.param添加請(qǐng)求傳值
(4) ResultActions.accept()設(shè)置返回類型
(5) ResultActions.andExpect添加執(zhí)行完成后的斷言。
(6) ResultActions.andDo添加一個(gè)結(jié)果處理器,表示要對(duì)結(jié)果做點(diǎn)什么事情,比如處使用print()輸出整個(gè)響應(yīng)結(jié)果信息。
(7) ResultActions.andReturn表示執(zhí)行完成后返回相應(yīng)的結(jié)果。
四、Service層的單元測(cè)試


圖二


@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:獲取啟動(dòng)類,加載配置,尋找主配置啟動(dòng)類(被 @SpringBootApplication 注解的)?@RunWith(SpringRunner.class):讓JUnit運(yùn)行Spring的測(cè)試環(huán)境,獲得Spring環(huán)境的上下文的支持五、Controller層的單元測(cè)試
第四部分只是針對(duì)Service層做了測(cè)試,但是咱么也需要對(duì)Controller層(API)做測(cè)試,這時(shí)候就用到MockMvc了,它使得你無需啟動(dòng)項(xiàng)目工程就能測(cè)試這些接口
MockMvc實(shí)現(xiàn)了對(duì)Http請(qǐng)求的模擬,能夠直接使用網(wǎng)絡(luò)的形式,轉(zhuǎn)換到Controller的調(diào)用,這樣可以使得測(cè)試速度快、不依賴網(wǎng)絡(luò)環(huán)境,而且提供了一套驗(yàn)證的工具,這樣可以使得請(qǐng)求的驗(yàn)證統(tǒng)一而且很方便。
@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>:獲取啟動(dòng)類,加載配置,尋找主配置啟動(dòng)類(被 @SpringBootApplication 注解的)@RunWith(SpringRunner.class)>:讓JUnit運(yùn)行Spring的測(cè)試環(huán)境,獲得Spring環(huán)境的上下文的支持?@AutoConfigureMockMvc:用于自動(dòng)配置MockMvc,配置后MockMvc類可以直接注入,相當(dāng)于new MockMvc @Before:初始化方法 ,對(duì)于每一個(gè)測(cè)試方法都要執(zhí)行一次@Test
@Transactional
@Rollback()
public?void?save()?throws?Exception?{
????????String json"{……}";
//執(zhí)行一個(gè)RequestBuilder請(qǐng)求,會(huì)自動(dòng)執(zhí)行SpringMVC的流程并映射到相應(yīng)的控制器執(zhí)行處理;
????????mockMvc.perform(MockMvcRequestBuilders
????????????????.post("/XXX/save")
????????????????.content(json.getBytes())?//傳json參數(shù)
????????????????.accept(MediaType.APPLICATION_JSON)
????????????????.contentType(MediaType.APPLICATION_JSON_VALUE)
????????????????.header("Authorization","Bearer ********-****-****-****-************")
????????)
????????????????.andExpect(MockMvcResultMatchers.status().isOk())
????????????????.andDo(print());
????}@Transactional:開啟事務(wù)功能@Rollback(): 事務(wù)回滾,默認(rèn)是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運(yùn)行結(jié)果如下:
1. mockMvc.perform:執(zhí)行一個(gè)請(qǐng)求2. MockMvcRequestBuilders.get(“/XXX/get”):構(gòu)造一個(gè)請(qǐng)求,Post請(qǐng)求使用.post方法3. contentType(MediaType.APPLICATION_JSON_VALUE):代表發(fā)送端發(fā)送的數(shù)據(jù)格式是application/json;charset=UTF-84. accept(MediaType.APPLICATION_JSON):代表客戶端希望接受的數(shù)據(jù)類型為application/json;charset=UTF-85. header(“Authorization”,“Bearer XXXX”):代表在報(bào)文頭添加一些必須的信息,這里添加的是token6. ResultActions.andExpect:添加執(zhí)行完成后的斷言7. ResultActions.andExpect(MockMvcResultMatchers.status().isOk()):方法看請(qǐng)求的狀態(tài)響應(yīng)碼是否為200如果不是則拋異常,測(cè)試不通過8. ResultActions.andDo:添加一個(gè)結(jié)果處理器,表示要對(duì)結(jié)果做點(diǎn)什么事情,比如此處使用print():輸出整個(gè)響應(yīng)結(jié)果信息六、斷言的概念
1. 斷言(assert),是編程術(shù)語,表示為一些布爾表達(dá)式,程序員相信在程序中的某個(gè)特定點(diǎn)該表達(dá)式值為真。可以在任何時(shí)候啟用和禁用斷言驗(yàn)證,因此可以在測(cè)試時(shí)啟用斷言而在部署時(shí)禁用斷言。
2. 使用斷言是判斷一個(gè)函數(shù)或?qū)ο蟮囊粋€(gè)方法所產(chǎn)生的結(jié)果是否符合你期望那個(gè)結(jié)果。
七、新斷言assertThat使用
assertThat 的優(yōu)點(diǎn):
優(yōu)點(diǎn) 1:以前 JUnit 提供了很多的 assertion 語句,如:assertEquals,assertNotSame,assertFalse,assertTrue,assertNotNull,assertNull 等,現(xiàn)在有了 JUnit 4.4,一條 assertThat 即可以替代所有的 assertion 語句,這樣可以在所有的單元測(cè)試中只使用一個(gè)斷言方法,使得編寫測(cè)試用例變得簡(jiǎn)單,代碼風(fēng)格變得統(tǒng)一,測(cè)試代碼也更容易維護(hù)。
優(yōu)點(diǎn) 2:assertThat 使用了 Hamcrest 的 Matcher 匹配符,用戶可以使用匹配符規(guī)定的匹配準(zhǔn)則精確的指定一些想設(shè)定滿足的條件,具有很強(qiáng)的易讀性,而且使用起來更加靈活。
優(yōu)點(diǎn) 3:assertThat 不再像 assertEquals 那樣,使用比較難懂的“謂賓主”語法模式(如:assertEquals(3, x);),相反,assertThat 使用了類似于“主謂賓”的易讀語法模式(如:assertThat(x,is(3));),使得代碼更加直觀、易讀。
assertThat(?[value],?[matcher statement]?);value?:接下來想要測(cè)試的變量值;?matcher statement?:使用 Hamcrest 匹配符來表達(dá)的對(duì)前面變量所期望的值的聲明,如果 value 值與 matcher statement 所表達(dá)的期望值相符,則測(cè)試成功,否則測(cè)試失敗。
八、Postman與Spring Boot 單元測(cè)試的區(qū)別
1. Spring Boot的單元測(cè)試主要針對(duì)方法層面,可以測(cè)試Service層這類非對(duì)外暴露的接口的類中方法,并且可一次性批量測(cè)試多個(gè)方法、支持事務(wù)回滾。
2. Postman針對(duì)接口進(jìn)行http測(cè)試,我平時(shí)這個(gè)比較多,創(chuàng)建的測(cè)試接口可保存、分類。
九、Postman基本用法


