SpringBoot單元測試(二)MockMVC
介紹
MockMvc,從字面來理解,很好理解,主要是用來模擬MVC。簡單來說,就是模擬可以從客戶端請求後端的Controller類。
樣例:
1. 非自動注入式
TestApplicationTests類已經有@RunWith(SpringRunner.class)和@SpringBootTest註解了,具體參考上一篇文章
SpringBoot 單元測試(一)SpringBootTest
package com.orjrs.spring.test.unit; import com.orjrs.spring.test.TestApplicationTests; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.result.MockMvcResultHandlers; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; /** * MockMvcTest * * @author orjrs * @date 2018-10-06 20:15 */ @WebAppConfiguration // 1 public class MockMvcTest extends TestApplicationTests { @Autowired private WebApplicationContext webApplicationContext; private MockMvc mockMvc; @Before // @Test註解的方法執行前執行,MockMvcBuilder構造MockMvc例項 public void setUp() { mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); } @Test public void post() throws Exception { String name = "Smart LIU"; String msg = "您好"; mockMvc.perform( MockMvcRequestBuilders.post("/unit/sayHello/" + name + "/" + msg) .contentType(MediaType.APPLICATION_JSON_UTF8) //.content() ) .andExpect(MockMvcResultMatchers.status().isOk()) //.andExpect(MockMvcResultMatchers.content().contentType("text/plain;charset=UTF-8")) .andDo(MockMvcResultHandlers.print()) .andReturn(); } }
2. 自動注入
package com.orjrs.spring.test.unit; import com.orjrs.spring.test.TestApplicationTests; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.http.MediaType; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.result.MockMvcResultHandlers; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; /** * MockMvcTest * * @author orjrs * @date 2018-10-21 16:12 */ @WebAppConfiguration // 1 @AutoConfigureMockMvc // 開啟MockMvc自動註解 public class AutoMockMvcTest extends TestApplicationTests { // @Autowired // private WebApplicationContext webApplicationContext; @Autowired private MockMvc mockMvc; /*@Before // @Test註解的方法執行前執行,MockMvcBuilder構造MockMvc例項 public void setUp() { mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); }*/ @Test public void post() throws Exception { String name = "Smart LIU"; String msg = "您好"; mockMvc.perform( MockMvcRequestBuilders.post("/unit/sayHello/" + name + "/" + msg) .contentType(MediaType.APPLICATION_JSON_UTF8) //.content() ) .andExpect(MockMvcResultMatchers.status().isOk()) //.andExpect(MockMvcResultMatchers.content().contentType("text/plain;charset=UTF-8")) .andDo(MockMvcResultHandlers.print()) .andReturn(); } }
原始碼分析:
MockMvcBuilders: 主要是用來構造MockMvc的。它有兩個方法,如下:
public class MockMvcBuilders { public MockMvcBuilders() { } // 通過指定WebApplicationContext,根據上下文獲取相應的Controller來構建MockMvc public static DefaultMockMvcBuilder webAppContextSetup(WebApplicationContext context) { return new DefaultMockMvcBuilder(context); } // 通過引數直接指定一組控制器來構建MockMVC public static StandaloneMockMvcBuilder standaloneSetup(Object... controllers) { return new StandaloneMockMvcBuilder(controllers); } }
AbstractMockMvcBuilder還實現了ConfigurableMockMvcBuilder介面,即有以下方法
package org.springframework.test.web.servlet.setup;
import javax.servlet.Filter;
import org.springframework.test.web.servlet.MockMvcBuilder;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.ResultHandler;
import org.springframework.test.web.servlet.ResultMatcher;
public interface ConfigurableMockMvcBuilder<B extends ConfigurableMockMvcBuilder<B>> extends MockMvcBuilder {
<T extends B> T addFilters(Filter... var1);// 新增過濾器
<T extends B> T addFilter(Filter var1, String... var2);// 新增過濾器
<T extends B> T defaultRequest(RequestBuilder var1);//預設的RequestBuilder,每次執行時會合併到自定義的RequestBuilder中,即提供公共請求資料的;
<T extends B> T alwaysExpect(ResultMatcher var1); // 定義全域性的結果驗證器,即每次執行請求時都進行驗證的規則;
<T extends B> T alwaysDo(ResultHandler var1);// 定義全域性結果處理器,即每次請求時都進行結果處理;
<T extends B> T dispatchOptions(boolean var1); // DispatcherServlet是否分發OPTIONS請求方法到控制器;
<T extends B> T apply(MockMvcConfigurer var1);
}
public interface MockMvcBuilder {
MockMvc build();
}
StandaloneMockMvcBuilder除了繼承AbstractMockMvcBuilder之外,自己還提供了許多方法,這裡不多說了。
MockMvc:
mockMvc.perform(
MockMvcRequestBuilders.post("/unit/sayHello/" + name + "/" + msg)
.contentType(MediaType.APPLICATION_JSON_UTF8)
//.content()
)
.andExpect(MockMvcResultMatchers.status().isOk())
//.andExpect(MockMvcResultMatchers.content().contentType("text/plain;charset=UTF-8"))
.andDo(MockMvcResultHandlers.print())
.andReturn();
}
perform:執行一個RequestBuilder請求,會自動執行SpringMVC的流程並對映到相應的控制器執行處理,返回ResultActions類;
andExpect:新增ResultMatcher驗證規則,驗證控制器執行完成後結果是否正確;
andDo:新增ResultHandler結果處理器,比如除錯時列印結果到控制檯;
andReturn:最後返回相應的MvcResult;然後進行自定義驗證/進行下一步的非同步處理;
另外還提供了以下API:
setDefaultRequest:設定預設的RequestBuilder,用於在每次perform執行相應的RequestBuilder時自動把該預設的RequestBuilder合併到perform的RequestBuilder中;
setGlobalResultMatchers:設定全域性的預期結果驗證規則,如我們通過MockMvc測試多個控制器時,假設它們都想驗證某個規則時,就可以使用這個;
setGlobalResultHandlers:設定全域性的ResultHandler結果處理器;
RequestBuilder/MockMvcRequestBuilders
Request請求,有put、get、post、delete、patch、options、head、request、multipart、fileUpload、asyncDispatch請求方法。
MockHttpServletRequestBuilder和MockMultipartHttpServletRequestBuilder
主要是針對請求頭的。有header、contentType、cookie、characterEncoding、requestAttr、sessionAttr、contextPath等方法