SpringBoot2.2之后用的Junit5,所以在這里使用的Junit5。Spring Boot會默認幫我們導入包,所以不用添加依賴了。
注解:
@BeforeAll : 只執行一次,執行時機是在所有測試和 @BeforeEach 注解方法之前。
@BeforeEach:在每個測試執行之前執行。
@AfterEach :在每個測試執行之后執行。
@AfterAll: 只執行一次,執行時機是在所有測試和 @AfterEach 注解方法之后。
測試一下,代碼如下
package com.example.demo; import org.junit.jupiter.api.*; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.web.servlet.MockMvc; @SpringBootTest class DemoApplicationTests { private MockMvc mockMvc; @BeforeAll public static void beforeAll(){ System.out.println("begin All"); } @BeforeEach public void beforeEach(){ System.out.println("begin Each"); } @Test public void test1(){ System.out.println("test1"); } @Test public void test2(){ System.out.println("test2"); } @AfterEach public void afterEach(){ System.out.println("end Each"); } @AfterAll public static void afterAll(){ System.out.println("end All"); } }
最終的輸出結果為:
begin All
begin Each
test1
end Each
begin Each
test2
end Each
end All
assert(斷言)。一般的斷言,無非是檢查一個實例的屬性(比如,判空與判非空等),或者對兩個實例進行比較(比如,檢查兩個實例對象是否相等)等
-
assertEquals(A,B,"message")
,判斷A對象和B對象是否相等,這個判斷在比較兩個對象時調用了equals()
方法。 -
assertSame(A,B,"message")
,判斷A對象與B對象是否相同,使用的是==
操作符。 -
assertTrue(A,"message")
,判斷A條件是否為真。 -
assertFalse(A,"message")
,判斷A條件是否不為真。 -
assertNotNull(A,"message")
,判斷A對象是否不為null
。 -
assertArrayEquals(A,B,"message")
,判斷A數組與B數組是否相等
MockMvc。對Controller的測試需要用到MockMvc技術
首先初始化MockMvc
private MockMvc mockMvc; @Autowired private WebApplicationContext wac; @Before public void setupMockMvc(){ mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); }
然后使用mockMvc模擬請求
模擬get請求帶參數
mockMvc.perform(MockMvcRequestBuilders.get("/hello?name={name}","zeng"));
模擬post請求
mockMvc.perform(MockMvcRequestBuilders.post("/user").param("name", "zhang")) //執行傳遞參數的POST請求(也可以post("/user?name=zhang"))
模擬文件上傳
mockMvc.perform(MockMvcRequestBuilders.fileUpload("/fileupload").file("file", "文件內容".getBytes("utf-8")));
也可以直接使用MultiValueMap
構建參數
MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>(); params.add("name", "zeng"); params.add("password", "123"); params.add("id", "1"); mockMvc.perform(MockMvcRequestBuilders.get("/stu").params(params));
模擬session和cookie
mockMvc.perform(MockMvcRequestBuilders.get("/index").sessionAttr(name, value)); mockMvc.perform(MockMvcRequestBuilders.get("/index").cookie(new Cookie(name, value)));
模擬HTTP請求頭:
mockMvc.perform(MockMvcRequestBuilders.get("/user/{id}", 1).header(name, values));
設置請求的Content-Type:
mockMvc.perform(MockMvcRequestBuilders.get("/index").contentType(MediaType.APPLICATION_JSON_UTF8));
設置返回格式為JSON:
mockMvc.perform(MockMvcRequestBuilders.get("/user/{id}", 1).accept(MediaType.APPLICATION_JSON));
mockMvc處理返回結果
期望成功調用,即HTTP Status為200:
mockMvc.perform(MockMvcRequestBuilders.get("/user/{id}", 1))
.andExpect(MockMvcResultMatchers.status().isOk());
期望返回內容是application/json
:
mockMvc.perform(MockMvcRequestBuilders.get("/user/{id}", 1))
.andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON));
檢查返回JSON數據中某個值的內容:
mockMvc.perform(MockMvcRequestBuilders.get("/user/{id}", 1))
.andExpect(MockMvcResultMatchers.jsonPath("$.name").value("zzz"))
這里使用到了jsonPath
,$
代表了JSON的根節點.
比較返回內容,使用content()
:
// 返回內容為hello mockMvc.perform(MockMvcRequestBuilders.get("/index")) .andExpect(MockMvcResultMatchers.content().string("hello")); // 返回內容是XML,並且與xmlCotent一樣 mockMvc.perform(MockMvcRequestBuilders.get("/index")) .andExpect(MockMvcResultMatchers.content().xml(xmlContent)); // 返回內容是JSON ,並且與jsonContent一樣 mockMvc.perform(MockMvcRequestBuilders.get("/index")) .andExpect(MockMvcResultMatchers.content().json(jsonContent));
比較forward或者redirect:
mockMvc.perform(MockMvcRequestBuilders.get("/index")) .andExpect(MockMvcResultMatchers.forwardedUrl("index.html")); // 或者 mockMvc.perform(MockMvcRequestBuilders.get("/index")) .andExpect(MockMvcResultMatchers.redirectedUrl("index.html"));
輸出響應結果:
mockMvc.perform(MockMvcRequestBuilders.get("/index")) .andDo(MockMvcResultHandlers.print());
在測試過程中如果要對數據庫添加、刪除、修改數據可以使用@Transactional,使數據能夠回滾。