日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

基于Mock測試Spring MVC接口過程解析

瀏覽:88日期:2023-08-01 15:59:31

1. 前言

在Java開發中接觸的開發者大多數不太注重對接口的測試,結果在聯調對接中出現各種問題。也有的使用Postman等工具進行測試,雖然在使用上沒有什么問題,如果接口增加了權限測試起來就比較惡心了。所以建議在單元測試中測試接口,保證在交付前先自測接口的健壯性。今天就來分享一下胖哥在開發中是如何對Spring MVC接口進行測試的。

在開始前請務必確認添加了Spring Boot Test相關的組件,在最新的版本中應該包含以下依賴:

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions></dependency>

本文是在Spring Boot 2.3.4.RELEASE下進行的。

2. 單獨測試控制層

如果我們只需要對控制層接口(Controller)進行測試,且該接口不依賴@Service、@Component等注解聲明的Spring Bean時,可以借助@WebMvcTest來啟用只針對Web控制層的測試,例如

@WebMvcTestclass CustomSpringInjectApplicationTests { @Autowired MockMvc mockMvc; @SneakyThrows @Test void contextLoads() { mockMvc.perform(MockMvcRequestBuilders.get('/foo/map')).andExpect(ResultMatcher.matchAll(status().isOk(), content().contentType(MediaType.APPLICATION_JSON), jsonPath('$.test', Is.is('hello')))).andDo(MockMvcResultHandlers.print()); }}

這種方式要快的多,它只加載了應用程序的一小部分。但是如果你涉及到服務層這種方式是不湊效的,我們就需要另一種方式了。

3. 整體測試

大多數Spring Boot下的接口測試是整體而又全面的測試,涉及到控制層、服務層、持久層等方方面面,所以需要加載比較完整的Spring Boot上下文。這時我們可以這樣做,聲明一個抽象的測試基類:

package cn.felord.custom;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.test.web.servlet.MockMvc;/** * 測試基類, * @author felord.cn */@SpringBootTest@AutoConfigureMockMvcabstract class CustomSpringInjectApplicationTests { /** * The Mock mvc. */ @Autowired MockMvc mockMvc; // 其它公共依賴和處理方法 }

只有當@AutoConfigureMockMvc存在時MockMvc才會被注入Spring IoC。

然后針對具體的控制層進行如下測試代碼的編寫:

package cn.felord.custom;import lombok.SneakyThrows;import org.hamcrest.core.Is;import org.junit.jupiter.api.Test;import org.springframework.http.MediaType;import org.springframework.test.web.servlet.ResultMatcher;import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;import org.springframework.test.web.servlet.result.MockMvcResultHandlers;import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;/** * 測試FooController. * * @author felord.cn */public class FooTests extends CustomSpringInjectApplicationTests { /** * /foo/map接口測試. */ @SneakyThrows @Test void contextLoads() { mockMvc.perform(MockMvcRequestBuilders.get('/foo/map')).andExpect(ResultMatcher.matchAll(status().isOk(), content().contentType(MediaType.APPLICATION_JSON), jsonPath('$.test', Is.is('bar')))).andDo(MockMvcResultHandlers.print()); }}

4. MockMvc測試

集成測試時,希望能夠通過輸入URL對Controller進行測試,如果通過啟動服務器,建立http client進行測試,這樣會使得測試變得很麻煩,比如,啟動速度慢,測試驗證不方便,依賴網絡環境等,為了可以對Controller進行測試就引入了MockMvc。

MockMvc實現了對Http請求的模擬,能夠直接使用網絡的形式,轉換到Controller的調用,這樣可以使得測試速度快、不依賴網絡環境,而且提供了一套驗證的工具,這樣可以使得請求的驗證統一而且很方便。接下來我們來一步步構造一個測試的模擬請求,假設我們存在一個下面這樣的接口:

@RestController@RequestMapping('/foo')public class FooController { @Autowired private MyBean myBean; @GetMapping('/user') public Map<String, String> bar(@RequestHeader('Api-Version') String apiVersion, User user) { Map<String, String> map = new HashMap<>(); map.put('test', myBean.bar()); map.put('version', apiVersion); map.put('username', user.getName()); //todo your business return map; }}

參數設定為name=felord.cn&age=18,那么對應的HTTP報文是這樣的:

GET /foo/user?name=felord.cn&age=18 HTTP/1.1Host: localhost:8888Api-Version: v1

可以預見的返回值為:

{ 'test': 'bar', 'version': 'v1', 'username': 'felord.cn'}

事實上對接口的測試可以分為以下幾步。

構建請求

構建請求由MockMvcRequestBuilders負責,他提供了請求方法(Method),請求頭(Header),請求體(Body),參數(Parameters),會話(Session)等所有請求的屬性構建。/foo/user接口的請求可以轉換為:

MockMvcRequestBuilders.get('/foo/user').param('name', 'felord.cn').param('age', '18').header('Api-Version', 'v1')

執行Mock請求

然后由MockMvc執行Mock請求:

mockMvc.perform(MockMvcRequestBuilders.get('/foo/user').param('name', 'felord.cn').param('age', '18').header('Api-Version', 'v1'))

對結果進行處理

請求結果被封裝到ResultActions對象中,它封裝了多種讓我們對Mock請求結果進行處理的方法。

對結果進行預期期望

ResultActions#andExpect(ResultMatcher matcher)方法負責對響應的結果的進行預期期望,看看是否符合測試的期望值。參數ResultMatcher負責從響應對象中提取我們需要期望的部位進行預期比對。

假如我們期望接口/foo/user返回的是JSON,并且HTTP狀態為200,同時響應體包含了version=v1的值,我們應該這么聲明:

ResultMatcher.matchAll(MockMvcResultMatchers.status().isOk(),MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON),MockMvcResultMatchers.jsonPath('$.version', Is.is('v1')));

JsonPath是一個強大的JSON解析類庫,請通過其項目倉庫https://github.com/json-path/JsonPath了解。

對響應進行處理

ResultActions#andDo(ResultHandler handler)方法負責對整個請求/響應進行打印或者log輸出、流輸出,由MockMvcResultHandlers工具類提供這些方法。我們可以通過以上三種途徑來查看請求響應的細節。

例如/foo/user接口:

MockHttpServletRequest: HTTP Method = GET Request URI = /foo/user Parameters = {name=[felord.cn], age=[18]} Headers = [Api-Version:'v1'] Body = null Session Attrs = {}Handler: Type = cn.felord.xbean.config.FooController Method = cn.felord.xbean.config.FooController#urlEncode(String, Params)Async: Async started = false Async result = nullResolved Exception: Type = nullModelAndView: View name = null View = null Model = nullFlashMap: Attributes = nullMockHttpServletResponse: Status = 200 Error message = null Headers = [Content-Type:'application/json'] Content type = application/json Body = {'test':'bar','version':'v1','username':'felord.cn'} Forwarded URL = null Redirected URL = null Cookies = []

獲取返回結果

如果你希望進一步處理響應的結果,也可以通過ResultActions#andReturn()拿到MvcResult類型的結果進行進一步的處理。

完整的測試過程

通常andExpect是我們必然會選擇的,而andDo和andReturn在某些場景下會有用,它們兩個是可選的。我們把上面的連在一起。

@AutowiredMockMvc mockMvc;@SneakyThrows@Testvoid contextLoads() { mockMvc.perform(MockMvcRequestBuilders.get('/foo/user') .param('name', 'felord.cn') .param('age', '18') .header('Api-Version', 'v1')) .andExpect(ResultMatcher.matchAll(status().isOk(), content().contentType(MediaType.APPLICATION_JSON), jsonPath('$.version', Is.is('v1')))) .andDo(MockMvcResultHandlers.print()); }

這種流式的接口單元測試從語義上看也是比較好理解的,你可以使用各種斷言、正例、反例測試你的接口,最終讓你的接口更加健壯。

5. 總結

一旦你熟練了這種方式,你編寫的接口將更加具有權威性而不會再漏洞百出,甚至有時候你也可以使用Mock來設計接口,使之更加貼合業務。所以CRUD不是完全沒有技術含量,高質量高效率的CRUD往往需要這種工程化的單元測試來支撐。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持好吧啦網。

標簽: Spring
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
免费黄网站欧美| 欧美精品日日操| 国产精品白浆| 精品国产欧美| 成人免费一区| 久久www成人_看片免费不卡| 国产精品xxx| 国产亚洲精品美女久久| 国产一区成人| 亚洲精品第一| 日韩欧美中文字幕一区二区三区| 美女黄网久久| 亚洲欧美日韩国产| 男女男精品网站| 日韩一区二区三区精品| 亚州国产精品| 美美哒免费高清在线观看视频一区二区| 欧美1级日本1级| 美女视频网站久久| 日本美女一区| 国产亚洲一区在线| 国产96在线亚洲| 亚洲欧美久久久| 四季av一区二区凹凸精品| 亚洲一区国产一区| sm久久捆绑调教精品一区| 蘑菇福利视频一区播放| 精品国产91| 日韩欧美久久| 婷婷亚洲五月| 九九久久国产| 视频一区视频二区在线观看| 国产福利片在线观看| 欧美日韩在线精品一区二区三区激情综合 | 男女男精品网站| 99热精品久久| 国产免费成人| 在线免费观看亚洲| 99pao成人国产永久免费视频 | 欧美色图国产精品| 日韩精品高清不卡| 性一交一乱一区二区洋洋av| 国产66精品| 国产视频网站一区二区三区| 亚洲视频www| 亚洲香蕉网站| 国产精品蜜芽在线观看| 欧美黄色一区二区| 国产精品久久久久久模特| 91麻豆精品| 日韩高清中文字幕一区| 青草av.久久免费一区| 日韩美女国产精品| 99精品国产一区二区三区| 国产成人精品免费视| 97在线精品| yellow在线观看网址| 国产一区二区精品久| 国产精品一级| 久久精品av麻豆的观看方式| 日韩高清不卡一区| 亚洲人成在线影院| 欧美有码在线| 国内不卡的一区二区三区中文字幕| 高清久久一区| 亚洲国产专区校园欧美| 成人啊v在线| 欧美丝袜一区| 蜜桃av一区二区| 欧美日一区二区在线观看| 欧美国产专区| 久久高清免费| 亚洲日韩视频| 国产极品一区| 亚洲成av人片一区二区密柚| 久久精品国产久精国产| 欧美日韩国产免费观看视频| 亚洲欧洲专区| 福利视频一区| 日韩国产在线观看| 99久久婷婷| 国产综合婷婷| 免费不卡在线观看| 国产精品久久乐| 日韩精品欧美| 日韩中文字幕视频网| 久久爱www成人| 国产精品久久久久av电视剧| 欧美日韩在线二区| 视频一区二区三区在线| 久久国产精品色av免费看| 97精品97| 青草国产精品| 亚洲午夜久久久久久尤物 | 日韩av一级| 蜜臀av在线播放一区二区三区| 国产精品一区二区三区av麻| 精品日韩一区| 久久亚洲二区| 麻豆国产欧美一区二区三区| 国产一区日韩一区| 欧美亚洲tv| 麻豆精品蜜桃| 国产亚洲一区| 性欧美xxxx免费岛国不卡电影| 日本精品久久| 国产精品社区| 久久久久久久久丰满| 欧美视频二区| 日韩精品一二三区| 麻豆视频在线观看免费网站黄| 合欧美一区二区三区| 欧美国产三级| 日本在线不卡视频一二三区| 欧美亚洲国产激情| 精品亚洲a∨| 亚洲欧美不卡| 日韩成人三级| 精品国产鲁一鲁****| 日韩欧美高清一区二区三区| 精品捆绑调教一区二区三区| 欧美a级一区二区| 日韩高清一区在线 | 一本大道色婷婷在线| 欧美特黄一区| 国产亚洲一区在线| 精品久久91| 麻豆精品国产91久久久久久| 日韩一区二区三区免费视频| 久久久天天操| 久久久久一区| jiujiure精品视频播放| 国产 日韩 欧美一区| 国产九九精品| 国产精品天天看天天狠| 午夜视频一区二区在线观看| 免费中文字幕日韩欧美| 中文日韩欧美| 三级在线观看一区二区| 亚洲理论在线| 欧美视频精品全部免费观看| 91成人小视频| 久久不见久久见中文字幕免费 | 色综合www| 日本欧美韩国一区三区| 亚洲综合中文| 蜜桃久久久久久| 青草国产精品久久久久久| 91福利精品在线观看| 欧美激情久久久久久久久久久| 精品福利久久久| 久久美女性网| 在线日韩成人| 国产一区二区三区网| 久久久精品网| 中文字幕av一区二区三区人| 国产日韩在线观看视频| 免费一级欧美片在线观看网站| 成人免费一区| 日韩精品一卡二卡三卡四卡无卡| 日本午夜免费一区二区| а√在线中文在线新版| 蜜桃av一区二区| 色偷偷偷在线视频播放| 中文不卡在线| 国产亚洲精品美女久久| 蜜桃视频在线观看一区二区| 亚洲一区成人| 亚洲最新av| av资源中文在线| 精品1区2区3区4区| 国产精品4hu.www| 日韩欧美字幕| 亚洲调教视频在线观看| 国产日产一区| 91精品一区二区三区综合| 免费成人在线观看| 91精品韩国| 精品久久99| 青青青国产精品| 91精品福利| 中文字幕一区久| 国产欧美丝祙| 性一交一乱一区二区洋洋av| 桃色一区二区| 精品亚洲免a| 欧美国产中文高清| 日本中文字幕一区二区| 青青草精品视频| 欧美日韩免费观看一区=区三区| 久久久久美女| 高清在线一区| 欧美伊人影院| 亚洲欧美专区| 激情欧美亚洲| 久久久久久一区二区| 国产精品中文字幕亚洲欧美| 亚洲欧美专区| 亚洲三级精品| 亚洲狼人精品一区二区三区|