日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

新來的騰訊后端,直接定義代碼測試新姿勢!

來源: 責編: 時間:2024-06-25 17:19:31 181觀看
導讀在日常工作中,看過很多開發人員不寫代碼測試,大部分理由是“太忙“或者”沒必要”,更嚴重的是很多開發人員甚至不知道如何寫測試代碼,本文我們總結了一位騰訊后端對 Controller層代碼優秀的測試經驗,希望對你有幫助。在 如

在日常工作中,看過很多開發人員不寫代碼測試,大部分理由是“太忙“或者”沒必要”,更嚴重的是很多開發人員甚至不知道如何寫測試代碼,本文我們總結了一位騰訊后端對 Controller層代碼優秀的測試經驗,希望對你有幫助。nqS28資訊網——每日最新資訊28at.com

nqS28資訊網——每日最新資訊28at.com

在 如何編寫優雅的 Controller代碼? 這篇文章中,我們分析了 Controller層的 6個主要職責,本文將分析如何對 Controller層進行360度無死角測試,首先回顧下 Controller層的6個主要職責:nqS28資訊網——每日最新資訊28at.com

  • 接收 HTTP(s)請求
  • 解析請求參數
  • 校驗請求參數
  • 調用業務方法
  • 組織返回數據
  • 統一異常處理

理解了 Controller的職責,才能更有目的對它進行測試,如下代碼,包含了 6個主要職責,我們該如何編寫測試代碼?nqS28資訊網——每日最新資訊28at.com

@RestControllerpublic class UserController {    private final UserService userService;    public UserController(UserService userService) {        this.userService = userService;    }    @PostMapping("/user/register")    public String getGradeById(@Validated @RequestBody User user) {        // 調用注冊的業務方法        String userId = userService.register(user);        return userId;    }}public class User {    @NotBlank(message = "Nickname is required.")    private String nickname;    private Integer age;    // getters and setters and constructors}

為什么要測試?

作為一名程序員,代碼質量是我們必須守住的底線,對于自己編寫的代碼一定需要經過測試,而不是把測試工作不負責的全部交給測試人員。nqS28資訊網——每日最新資訊28at.com

對于開發人員,保證代碼質量最有效的方式是測試,最常見的測試方式有 2種:單元測試(Unit Testing)和 集成測試(Integration Testing)。nqS28資訊網——每日最新資訊28at.com

單元測試的目的是驗證單個功能單元的行為是否正確,這里的功能單元通常是一個類或方法,單元測試最大的優點是可以在不依賴于其他部分的前提下測試某個功能單元。nqS28資訊網——每日最新資訊28at.com

集成測試的目的是驗證多個功能單元之間的交互是否正確,可能涉及數據庫、文件系統、網絡等外部系統,如果需要排除外部系統的干擾,可以對他們進行 mock。nqS28資訊網——每日最新資訊28at.com

如何測試?

對于 Controller層的代碼測試,因為單元測試的局限性,所以我們需要采用集成測試,本文將使用SpringBootTest 和 Mockito兩個主流的測試框架進行分析,下面先說明幾個重要的組件:nqS28資訊網——每日最新資訊28at.com

1.@WebMvcTest

@WebMvcTest是 Spring Boot提供的一個注解,用于測試 SpringMVC的 Controller,它能夠啟動一個最小化的 Spring應用上下文,包含僅與 Web層相關的 bean,從而快速且高效地測試 Controller的功能。nqS28資訊網——每日最新資訊28at.com

@WebMvcTest主要功能如下:nqS28資訊網——每日最新資訊28at.com

  • 加載 Web層相關的 Bean: @WebMvcTest只加載與 Web層相關的 bean,例如 Controller、過濾器、攔截器等,這使得測試環境更加輕量級。
  • 自動配置 MockMvc: @WebMvcTest 自動配置 MockMvc,使得測試控制器的 HTTP請求處理變得簡單。
  • 支持 @MockBean注解: 可以使用 @MockBean注解來模擬服務層的 bean,以隔離控制器測試,不依賴實際的服務層實現。

2.MockMvc

MockMvc是 Spring框架中用于測試 Spring MVC控制器的主要工具,它允許開發者在不啟動整個 HTTP服務器的情況下,測試控制器的請求處理方法。MockMvc 提供了一種方式來模擬 HTTP請求并驗證響應,確保控制器行為符合預期。nqS28資訊網——每日最新資訊28at.com

MockMvc的主要功能如下:nqS28資訊網——每日最新資訊28at.com

  • 模擬 HTTP 請求: MockMvc 可以模擬各種 HTTP 請求,如 GET、POST、PUT、DELETE 等。
  • 驗證響應: MockMvc 提供了一組豐富的斷言來驗證響應的狀態碼、內容類型、內容、頭信息等。
  • 測試控制器邏輯: 通過模擬請求并驗證響應,可以測試控制器的業務邏輯、路徑變量、請求參數、請求體等。
  • 集成測試: 可以與 Spring 的其他測試工具結合,進行更復雜的集成測試。

3.Mockito

Mockito 是一個流行的 Java測試框架,用于創建和配置 mock 對象。它主要用于單元測試中,通過模擬依賴對象的行為,使得測試目標對象能夠獨立于其依賴項進行測試。nqS28資訊網——每日最新資訊28at.com

Mockito主要功能如下:nqS28資訊網——每日最新資訊28at.com

  • 創建 Mock 對象: 使用 @Mock注解或 Mockito.mock()方法創建 mock對象。
  • 定義行為: 使用 when 和 thenReturn 等方法定義 mock 對象的方法行為。
  • 驗證行為: 使用 verify 方法驗證 mock 對象的方法是否被調用,以及調用的次數和參數。
  • 參數匹配: 使用 any、eq 等參數匹配器來驗證方法調用時傳入的參數。
  • 模擬異常: 使用 thenThrow 方法模擬方法拋出異常的行為。

4.ObjectMapper

它是 Jackson庫中的核心類之一,用于將 Java 對象轉換為 JSON 字符串,或者將 JSON 字符串轉換為 Java 對象。在 Spring 應用中,ObjectMapper 被廣泛用于處理 JSON 數據。nqS28資訊網——每日最新資訊28at.com

ObjectMapper的主要功能如下:nqS28資訊網——每日最新資訊28at.com

  • 序列化(Serialization): 將 Java 對象轉換為 JSON 字符串。
  • 反序列化(Deserialization): 將 JSON 字符串轉換為 Java 對象。
  • 讀取和寫入 JSON 文件或流: 直接從文件、輸入流讀取 JSON 數據,或將 JSON 數據寫入文件、輸出流。

所以,一個包含上述所有組件的完整代碼示例如下:nqS28資訊網——每日最新資訊28at.com

@WebMvcTest(controllers = RegisterRestController.class)class RegisterRestControllerTest {  @Autowired  private MockMvc mockMvc;  @Autowired  private ObjectMapper objectMapper;  @MockBean  private XXX xxx; // 用戶業務的bean  @Test  void test() throws Exception {    mockMvc.perform(...);  }}

介紹了上面幾個集成測試的組件之后,接下來我們就可以詳解的分析他們是如何應用到 Controller的集成測試中。nqS28資訊網——每日最新資訊28at.com

測試詳解

我們按照 Controller的 6個主要職責來分別講解他們是如何進行測試的。nqS28資訊網——每日最新資訊28at.com

1.測試接收 HTTP(s)請求

Controller是接收請求的入口,因此對于 Controller接收 HTTP(s)請求驗證 Controller是否偵聽某個 HTTP 請求非常簡單,我們只需調用 MockMvc.perform() 方法,返回 200代表成功,返回非200就代表異常,示例代碼如下:nqS28資訊網——每日最新資訊28at.com

@Testvoid whenReceiveHttpRqe_thenReturns200() throws Exception {    mockMvc.perform(post("/user/register")        .contentType("application/json"))        .andExpect(status().isOk()); }

2.測試解析請求參數

Controller是通過@PathVariable、@RequestBody、@RequestParam 3種方式來接收參數的,因此,下面的示例代碼分別模擬這 3種方式是如何進行參數傳遞的。nqS28資訊網——每日最新資訊28at.com

@Autowiredprivate ObjectMapper objectMapper;@Testvoid whenValidInput_thenReturns200() throws Exception {  User user = new User("zhangsan", 21);     mockMvc.perform(post("/user/register/{id}", 1111) // 模擬通過 @PathVariable傳遞參數        .contentType("application/json")        .param("name", "張三") // 模擬通過 @RequestParam傳遞參數        .content(objectMapper.writeValueAsString(user))) // 模擬通過 @RequestBody傳遞參數        .andExpect(status().isOk());}

通過上面的方式,我們模擬了一個正常的 HTTP請求,并且使用 3種方式進行參數傳遞。nqS28資訊網——每日最新資訊28at.com

3.測試校驗請求參數

測試參數的校驗,主要是為了檢查代碼邏輯有沒有對參數進行有效的驗證,比如,必填字段判空,字符串最大長度限制,數字最大值和最小值校驗,手機號或郵箱格式校驗等。nqS28資訊網——每日最新資訊28at.com

參數校驗測試一般分正常測試和按預期失敗的異常測試,特別需要進行邊界的測試。如下示例,給出了測試通過和符合預期并返回 400的 BadRequest:nqS28資訊網——每日最新資訊28at.com

public class User {    @NotBlank(message = "Nickname is required.")    private String nickname;    private Integer age;    // getters and setters and constructors}@Testvoid whenNicknameNull_thenReturns400() throws Exception {  User user = new User(null, 21); // 當 nickname為空時,會拋出 400的 BadRequest異常  mockMvc.perform(post("/user/register")      .content(objectMapper.writeValueAsString(user)))      .andExpect(status().isOk());}@Testvoid testReturns200() throws Exception {    User user = new User("zhangsan", 21);    mockMvc.perform(post("/user/register")        .content(objectMapper.writeValueAsString(user)))        .andExpect(status().isBadRequest());}

4.測試調用業務方法

對于業務方法調用的測試,通常我們會使用Mockito.mock來模擬業務方法的返回值,而業務方式的真實運行邏輯會在 Server的單元測試中完成,如下示例代碼:nqS28資訊網——每日最新資訊28at.com

// 調用注冊的業務方法String userId = userService.register(user);@Testvoid whenLogic_thenReturnsExceptData() throws Exception {    User user = new User(null, 21);    // mock userService.register(user)返回值為 userId    Mockito.when(userService.register(user)).thenReturn("userId");    mockMvc.perform(post("/user/register")                    .content(objectMapper.writeValueAsString(user)))            .andExpect(status().isOk())            .andExpect(jsonPath("$.data", is("userId")));}

5.測試組織返回數據

在業務代碼執行完之后,我們需要對 HTTP對應響應,因此可以使用 andReturn()方法將 HTTP交互的結果存儲在 MvcResult類型的變量中,然后從響應正文中讀取 JSON字符串,并使用 isEqualToIgnoringWhitespace()將其與預期字符串進行比較,如下示例:nqS28資訊網——每日最新資訊28at.com

// 調用注冊的業務方法String userId = userService.register(user);@Testvoid whenLogic_thenReturnsExceptData() throws Exception {    User user = new User("zhangsan", 21);    // mock userService.register(user)返回值為 userId    Mockito.when(userService.register(user)).thenReturn("userId");    MvcResult mvcResult = mockMvc.perform(post("/user/register")        .content(objectMapper.writeValueAsString(user)))        .andReturn(); //將結果返回    String expectedResponse = "userId";    String actualResponseBody = mvcResult.getResponse().getContentAsString();    assertThat(actualResponseBody).isEqualToIgnoringWhitespace(            objectMapper.writeValueAsString(expectedResponse));}

6.測試統一異常處理

測試異是指如果發生異常,Controller應返回特定的 HTTP狀態,比如 200,400,500等等, 默認情況下,Spring 會處理其中的大多數情況。但是,如果我們有一個自定義異常處理,我們想要測試它。假設我們要返回一個結構化的 JSON 錯誤響應,其中包含請求中每個無效字段的字段名稱和錯誤消息。我們會創建一個這樣的@ControllerAdvice:nqS28資訊網——每日最新資訊28at.com

@Testvoid whenNullValue_thenReturns400AndErrorResult() throws Exception {  User user = new User("zhangsan", 21);  MvcResult mvcResult = mockMvc.perform(post("/user/register")          .contentType("application/json")          .content(objectMapper.writeValueAsString(user)))          .andExpect(status().isBadRequest())          .andReturn();  ErrorResult expectedErrorResponse = new ErrorResult("Nickname", "Nickname is required.");  String actualResponse = mvcResult.getResponse().getContentAsString();  String expectedResponseBody = objectMapper.writeValueAsString(expectedErrorResponse);  assertThat(actualResponse).isEqualToIgnoringWhitespace(expectedErrorResponse);}

總結

本文結合 SpringBootTest 和 Mockito兩個主流的測試框架,對 Controller各個職責進行全面的測試,并且給出了比較詳細的示例代碼,通過本文的分析,我們不僅可以學會對 Controller的測試,同時還應該觸類旁通,將里面優秀的思維應用到其他層級代碼的測試。nqS28資訊網——每日最新資訊28at.com

代碼質量是開發人員必須守住的底線,所以在日常的開發中一定要秉著對自己負責的態度,采用單元測試和集成測試對自己的代碼進行測試。nqS28資訊網——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-96427-0.html新來的騰訊后端,直接定義代碼測試新姿勢!

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 2024 Vue 最全的生態工具組合推薦指南

下一篇: CVPR 2024 | PICO 交互感知團隊 - 從圖像到可驅動形象:OHTA 實現單圖創建手部化身

標簽:
  • 熱門焦點
  • 5月iOS設備性能榜:M1 M2依舊是榜單前五

    和上個月一樣,沒有新品發布的iOS設備性能榜的上榜設備并沒有什么更替,僅僅只有跑分變化而產生的排名變動,剛剛開始的蘋果WWDC2023,推出的產品也依舊是新款Mac Pro、新款Mac Stu
  • 28個SpringBoot項目中常用注解,日常開發、求職面試不再懵圈

    前言在使用SpringBoot開發中或者在求職面試中都會使用到很多注解或者問到注解相關的知識。本文主要對一些常用的注解進行了總結,同時也會舉出具體例子,供大家學習和參考。注解
  • 把LangChain跑起來的三個方法

    使用LangChain開發LLM應用時,需要機器進行GLM部署,好多同學第一步就被勸退了,那么如何繞過這個步驟先學習LLM模型的應用,對Langchain進行快速上手?本片講解3個把LangChain跑起來
  • 多線程開發帶來的問題與解決方法

    使用多線程主要會帶來以下幾個問題:(一)線程安全問題  線程安全問題指的是在某一線程從開始訪問到結束訪問某一數據期間,該數據被其他的線程所修改,那么對于當前線程而言,該線程
  • 虛擬鍵盤 API 的妙用

    你是否在遇到過這樣的問題:移動設備上有一個固定元素,當激活虛擬鍵盤時,該元素被隱藏在了鍵盤下方?多年來,這一直是 Web 上的默認行為,在本文中,我們將探討這個問題、為什么會發生
  • 騰訊VS網易,最卷游戲暑期檔,誰能笑到最后?

    作者:無銹缽來源:財經無忌7月16日晚,上海1862時尚藝術中心。伴隨著幻象的精準命中,碩大的熒幕之上,比分被定格在了14:12,被寄予厚望的EDG戰隊以絕對的優勢戰勝了BLG戰隊,拿下了總決
  • ESG的面子與里子

    來源 | 光子星球撰文 | 吳坤諺編輯 | 吳先之三伏大幕拉起,各地高溫預警不絕,但處于厄爾尼諾大“烤”之下的除了眾生,還有各大企業發布的ESG報告。ESG是“環境保
  • 當家的盒馬,加速謀生

    來源 | 價值星球Planet作者 | 歸去來自己“當家”的盒馬,開始加速謀生了。據盒馬官微消息,盒馬計劃今年開放生鮮供應鏈,將其生鮮商品送往食堂。目前,盒馬在上海已經與
  • 造車兩年股價跌六成,小米的估值邏輯變了嗎?

    如果從小米官宣造車后的首個交易日起持有小米集團的股票,那么截至2023年上半年最后一個交易日,投資者將浮虧59.16%,同區間的恒生科技指數跌幅為52.78%
Top 主站蜘蛛池模板: 烟台市| 惠安县| 贵港市| 佛学| 广西| 博客| 茂名市| 靖安县| 策勒县| 合肥市| 浪卡子县| 梅河口市| 永善县| 额尔古纳市| 基隆市| 伊金霍洛旗| 奉化市| 陆川县| 峨眉山市| 苗栗市| 平罗县| 河北省| 新和县| 荥经县| 宁国市| 雷山县| 宁安市| 铁岭市| 翼城县| 汶川县| 大庆市| 探索| 鹰潭市| 德惠市| 巴南区| 金门县| 来宾市| 通化县| 界首市| 恩施市| 左贡县|