測試是保證程序健壯的手段之一,也是非常重要的。今天我們來簡單的聊聊Spring boot 如何進行測試。
- 引入測試的jar
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
Spring boot 的測試只需要在測試類上加上@RunWith(SpringRunner.class),@SpringBootTest注解即可。SpringRunner.class 開啟了Spring集成測試;@SpringBootTest 在沒有配置上下文加載器的情況下默認(rèn)使用了Spring boot的上下文加載器,當(dāng)內(nèi)部的配置沒有使用,沒有明確的字節(jié)碼自動查找Spring boot配置,允許自定義屬性,支持不同的web環(huán)境,在web服務(wù)器中測試下注冊TestRestTemplate或者WebTestClient對象。準(zhǔn)備工作完成之后就可以進行測試了。對于@SpringBootTest 注解可以看看官方的注釋:
Annotation that can be specified on a test class that runs Spring Boot based tests.
Provides the following features over and above the regular <em>Spring TestContext
Framework</em>:
<ul>
<li>Uses {@link SpringBootContextLoader} as the default {@link ContextLoader} when no specific {@link ContextConfiguration#loader() @ContextConfiguration(loader=...)} is defined.</li>
<li>Automatically searches for a {@link SpringBootConfiguration @SpringBootConfiguration} when nested
{@code @Configuration} is not used, and no explicit {@link #classes() classes} are specified.</li>
<li>Allows custom {@link Environment} properties to be defined using the {@link #properties() properties attribute}.</li>
<li>Provides support for different {@link #webEnvironment() webEnvironment} modes,including the ability to start a fully running web server listening on a {@link WebEnvironment#DEFINED_PORT defined} or {@link WebEnvironment#RANDOM_PORT random} port.</li>
<li>Registers a {@link org.springframework.boot.test.web.client.TestRestTemplate
TestRestTemplate} and/or{@link org.springframework.test.web.reactive.server.WebTestClient WebTestClient} bean for use in web tests that are using a fully running web server.</li>
</ul>
-
Spring的測試
一、測試service層,通過@Autowired注入相對應(yīng)的bean即可。
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootApplicationTest {
@Autowired
private TestService testService;
@Test
public void test() {
testService.test();
}
}
二、Spring boot 進行web測試,Spring 3.2之后提供了mock mvc:能在一個近似真實的模擬Servlet容器里測試控制器,而不用實際啟動應(yīng)用服務(wù)器。接下來聊聊mock mvc是如何使用的。
可以使用MockMvcBuilders,該類提供了兩個靜態(tài)方法。
standaloneSetup():構(gòu)建一個Mock MVC,提供一個或多個手工創(chuàng)建并配置的控制器。
webAppContextSetup():使用Spring應(yīng)用程序上下文來構(gòu)建Mock MVC,該上下文里可以包含一個或多個配置好的控制器。
二則的區(qū)別在于:
standaloneSetup()希望你手工初始化并注入你要測試的控制器,而webAppContextSetup()則基于一個webApplicationContext的實例,通常由Spring加載。前者同單元測試更加接近,你可能只想讓它專注于單一控制器的測試,而后者讓Spring加載控制器及其依賴,以便進行完整的集成測試。
控制器類
@RestController
@RequestMapping(value = "/my")
public class MyController {
@RequestMapping(value = "/integration/{name}", method = RequestMethod.GET)
public String integrationTest(@PathVariable String name) {
return "name:" + name;
}
}
測試類
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootApplicationTest {
Logger logger = LoggerFactory.getLogger(SpringBootApplicationTest.class);
@Autowired
private WebApplicationContext context;
private MockMvc mvc;
@Before
public void setupMockMvc() {
// mvc = MockMvcBuilders.webAppContextSetup(context).build();
mvc= MockMvcBuilders.standaloneSetup(new MyController()).build();
}
@Test
public void getName() throws Exception {
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get("/my/integration/{name}", "lisi");
// MockMvcRequestBuilders.post()
// MockMvcRequestBuilders.delete()
// MockMvcRequestBuilders.put()
// ... 其他的http請求
// 請求接受類型
// builder.accept(MediaType.APPLICATION_JSON);
// 參數(shù)
// builder.param();
// 請求的body
// builder.content();
// ... 還有一些其他的請求參數(shù)設(shè)置,具體的可以查看api
// 打印并返回結(jié)果
MvcResult result = mvc.perform(builder)
// code 是否是200
.andExpect(MockMvcResultMatchers.status().isOk())
// 內(nèi)容是不是 name:lisi
.andExpect(MockMvcResultMatchers.content().string("name:lisi"))
// 打印
.andDo(MockMvcResultHandlers.print())
// 返回結(jié)果
.andReturn();
MockHttpServletResponse response = result.getResponse();
logger.info("響應(yīng)狀態(tài):{},響應(yīng)內(nèi)容:{}", response.getStatus(), response.getContentAsString());
}
}
-
RequestBuilder/MockMvcRequestBuilders
從名字可以看出,RequestBuilder用來構(gòu)建請求的,其提供了一個方法buildRequest(ServletContext servletContext)用于構(gòu)建MockHttpServletRequest;其主要有兩個子類MockHttpServletRequestBuilder和MockMultipartHttpServletRequestBuilder(如文件上傳使用),即用來Mock客戶端請求需要的所有數(shù)據(jù)。 - MockMvcRequestBuilders主要API
MockHttpServletRequestBuilder get(String urlTemplate, Object... urlVariables):根據(jù)uri模板和uri變量值得到一個GET請求方式的MockHttpServletRequestBuilder;如get(/user/{id}, 1L);
MockHttpServletRequestBuilder post(String urlTemplate, Object... urlVariables):同get類似,但是是POST方法;
MockHttpServletRequestBuilder put(String urlTemplate, Object... urlVariables):同get類似,但是是PUT方法;
MockHttpServletRequestBuilder delete(String urlTemplate, Object... urlVariables) :同get類似,但是是DELETE方法;
MockHttpServletRequestBuilder options(String urlTemplate, Object... urlVariables):同get類似,但是是OPTIONS方法;
MockHttpServletRequestBuilder request(HttpMethod httpMethod, String urlTemplate, Object... urlVariables): 提供自己的Http請求方法及uri模板和uri變量,如上API都是委托給這個API;
MockMultipartHttpServletRequestBuilder fileUpload(String urlTemplate, Object... urlVariables):提供文件上傳方式的請求,得到MockMultipartHttpServletRequestBuilder;
RequestBuilder asyncDispatch(final MvcResult mvcResult):創(chuàng)建一個從啟動異步處理的請求的MvcResult進行異步分派的RequestBuilder;
- MockHttpServletRequestBuilder和MockMultipartHttpServletRequestBuilder API
MockHttpServletRequestBuilder header(String name, Object... values)/MockHttpServletRequestBuilder headers(HttpHeaders httpHeaders):添加頭信息;
MockHttpServletRequestBuilder contentType(MediaType mediaType):指定請求的contentType頭信息;
MockHttpServletRequestBuilder accept(MediaType... mediaTypes)/MockHttpServletRequestBuilder accept(String... mediaTypes):指定請求的Accept頭信息;
MockHttpServletRequestBuilder content(byte[] content)/MockHttpServletRequestBuilder content(String content):指定請求Body體內(nèi)容;
MockHttpServletRequestBuilder cookie(Cookie... cookies):指定請求的Cookie;
MockHttpServletRequestBuilder locale(Locale locale):指定請求的Locale;
MockHttpServletRequestBuilder characterEncoding(String encoding):指定請求字符編碼;
MockHttpServletRequestBuilder requestAttr(String name, Object value) :設(shè)置請求屬性數(shù)據(jù);
MockHttpServletRequestBuilder sessionAttr(String name, Object value)/MockHttpServletRequestBuilder sessionAttrs(Map<string, object=""> sessionAttributes):設(shè)置請求session屬性數(shù)據(jù);
MockHttpServletRequestBuilder flashAttr(String name, Object value)/MockHttpServletRequestBuilder flashAttrs(Map<string, object=""> flashAttributes):指定請求的flash信息,比如重定向后的屬性信息;
MockHttpServletRequestBuilder session(MockHttpSession session) :指定請求的Session;
MockHttpServletRequestBuilder principal(Principal principal) :指定請求的Principal;
MockHttpServletRequestBuilder contextPath(String contextPath) :指定請求的上下文路徑,必須以“/”開頭,且不能以“/”結(jié)尾;
MockHttpServletRequestBuilder pathInfo(String pathInfo) :請求的路徑信息,必須以“/”開頭;
MockHttpServletRequestBuilder secure(boolean secure):請求是否使用安全通道;
MockHttpServletRequestBuilder with(RequestPostProcessor postProcessor):請求的后處理器,用于自定義一些請求處理的擴展點;
MockMultipartHttpServletRequestBuilder繼承自MockHttpServletRequestBuilder,又提供了如下API
MockMultipartHttpServletRequestBuilder file(String name, byte[] content)/MockMultipartHttpServletRequestBuilder file(MockMultipartFile file):指定要上傳的文件;
- ResultActions
調(diào)用MockMvc.perform(RequestBuilder requestBuilder)后將得到ResultActions,通過ResultActions完成如下三件事:
ResultActions andExpect(ResultMatcher matcher) :添加驗證斷言來判斷執(zhí)行請求后的結(jié)果是否是預(yù)期的;
ResultActions andDo(ResultHandler handler) :添加結(jié)果處理器,用于對驗證成功后執(zhí)行的動作,如輸出下請求/結(jié)果信息用于調(diào)試;
MvcResult andReturn() :返回驗證成功后的MvcResult;用于自定義驗證/下一步的異步處理;
- ResultMatcher/MockMvcResultMatchers
HandlerResultMatchers handler():請求的Handler驗證器,比如驗證處理器類型/方法名;此處的Handler其實就是處理請求的控制器;
RequestResultMatchers request():得到RequestResultMatchers驗證器;
ModelResultMatchers model():得到模型驗證器;
ViewResultMatchers view():得到視圖驗證器;
FlashAttributeResultMatchers flash():得到Flash屬性驗證;
StatusResultMatchers status():得到響應(yīng)狀態(tài)驗證器;
HeaderResultMatchers header():得到響應(yīng)Header驗證器;
CookieResultMatchers cookie():得到響應(yīng)Cookie驗證器;
ContentResultMatchers content():得到響應(yīng)內(nèi)容驗證器;
JsonPathResultMatchers jsonPath(String expression, Object ... args)/ResultMatcher jsonPath(String expression, Matcher matcher):得到Json表達式驗證器;
XpathResultMatchers xpath(String expression, Object... args)/XpathResultMatchers xpath(String expression, Map<string, string=""> namespaces, Object... args):得到Xpath表達式驗證器;
ResultMatcher forwardedUrl(final String expectedUrl):驗證處理完請求后轉(zhuǎn)發(fā)的url(絕對匹配);
ResultMatcher forwardedUrlPattern(final String urlPattern):驗證處理完請求后轉(zhuǎn)發(fā)的url(Ant風(fēng)格模式匹配,@since spring4);
ResultMatcher redirectedUrl(final String expectedUrl):驗證處理完請求后重定向的url(絕對匹配);
ResultMatcher redirectedUrlPattern(final String expectedUrl):驗證處理完請求后重定向的url(Ant風(fēng)格模式匹配,@since spring4);
今天先寫到這,后續(xù)還會有補充,更加詳細一點,然后還會有web安全測試,未完待續(xù)...若有什么問題或建議請聯(lián)系,郵箱guofei_wu@163.com。
參考文章:SpringMVC 測試 mockMVC