每個Java人都必須掌握的單元測試

前言

文本已收錄至我的GitHub倉庫,歡迎Star:https://github.com/bin392328206/six-finger
種一棵樹最好的時間是十年前,其次是現在
我知道很多人不玩qq了,但是懷舊一下,歡迎加入六脈神劍Java菜鳥學習羣,羣聊號碼:549684836 鼓勵大家在技術的路上寫博客

絮叨

最近再維護一個前人寫的系統,然後就發現了一個很大的問題,就是單元測試沒有寫,真的是心態崩潰,很多時候自己都不敢去改代碼,因爲怕一改代碼導致測試不到位,改多了bug,優化都不敢優化,只能說出現bug了,纔不得不改他的時候去改改。對於一個好的產品,六六覺得代碼的規範,可測試性,可拓展性,容錯性真的很重要。到後期的優化,重構全靠一期 二期的基礎,這些纔是一個產品能長久不衰的本質,但是目前大部分產品就是先活下來,然後再考慮這個問題,確實也是,因爲你活不下來,設計那麼好,又有啥用呢?但是作爲我們開發人員,可以自己多注意這些規範,說實話包括自己,以前碰到單元測試,我也不喜歡寫,因爲也許這個代碼一期是你開發的,後面都不一定是你去接手了,不過小六六得改掉這個習慣,以後自己的接口,儘量寫單元測試,算是立個flag吧。既然我用postMan,我爲啥不用mockMvc,我想缺點可能是每次的啓動時間有點長,如果項目很趕,可以放下,閒下來了,肯定得補的

使用junit測試業務層代碼


上面是一個分佈式頭條練習項目,我們可以看到他是一個標準的分佈式項目目錄結構,
然後我們找到我們要測試的service 然後 我們右鍵點擊他

然後你就可以直接創建你的測試類了

記得填好你下面的2個註解,你就可以愉快的做單元測試了。

使用mockmvc測試控制層代碼

爲何使用MockMvc

MockMvc實現了對Http請求的模擬,能夠直接使用網絡的形式,轉換到Controller的調用,這樣可以
使得測試速度快、不依賴網絡環境,而且提供了一套驗證的工具,這樣可以使得請求的驗證統一而
且很方便。

測試邏輯

  • MockMvcBuilder構造MockMvc的構造器
  • mockMvc調用perform,執行一個RequestBuilder請求,調用controller的業務處理邏輯
  • perform返回ResultActions,返回操作結果,通過ResultActions,提供了統一的驗證方式
  • 使用StatusResultMatchers對請求結果進行驗證
  • 使用ContentResultMatchers對請求返回的內容進行驗證

具體代碼

@RunWith(SpringRunner.class)
@SpringBootTest(classes = JunitApplication.class)
@WebAppConfiguration
public class JunitTestControllerTest {

    @Autowired
    private WebApplicationContext webApplicationContext;

    private MockMvc mvc;

    @Before
    public void setUp()throws Exception {
        mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }

    @Test
    public void helloJunit() throws Exception{

        /**
         * 1、mockMvc.perform執行一個請求。
         * 2、MockMvcRequestBuilders.get("XXX")構造一個請求。
         * 3、ResultActions.param添加請求傳值
         * 4、ResultActions.accept(MediaType.TEXT_HTML_VALUE))設置返回類型
         * 5、ResultActions.andExpect添加執行完成後的斷言。
         * 6、ResultActions.andDo添加一個結果處理器,表示要對結果做點什麼事情
         *   比如此處使用MockMvcResultHandlers.print()輸出整個響應結果信息。
         * 5、ResultActions.andReturn表示執行完成後返回相應的結果。
         */

        MvcResult mvcResult= mvc.perform(MockMvcRequestBuilders.get("/junit/helloJunit")
            // 參數傳遞
                .param("name","lvgang")
                .accept(MediaType.TEXT_HTML_VALUE))
                // .andExpect(MockMvcResultMatchers.status().isOk())             //等同於Assert.assertEquals(200,status);
                // .andExpect(MockMvcResultMatchers.content().string("hello lvgang"))    //等同於 Assert.assertEquals("hello lvgang",content);
                .andDo(MockMvcResultHandlers.print())
                .andReturn();
        int status=mvcResult.getResponse().getStatus();                 //得到返回代碼
        String content=mvcResult.getResponse().getContentAsString();    //得到返回結果

        Assert.assertEquals(200,status);                        //斷言,判斷返回代碼是否正確
        Assert.assertEquals("你好:Frank",content);            //斷言,判斷返回的值是否正確
    }
}

方法解析

  • **perform:**執行一個RequestBuilder請求,會自動執行SpringMVC的流程並映射到相應的控制器執行處理;
  • **get:**聲明發送一個get請求的方法。MockHttpServletRequestBuilder get(String urlTemplate, **Object…
  • urlVariables):**根據uri模板和uri變量值得到一個GET請求方式的。另外提供了其他的請求的方法,如:post、put、delete等。
  • **param:**添加request的參數,如上面發送請求的時候帶上了了pcode = - root的參數。假如使用需要發送json數據格式的時將不能使用這種方式,可見後面被@ResponseBody註解參數的解決方法
  • **andExpect:**添加ResultMatcher驗證規則,驗證控制器執行完成後結果是否正確(對返回的數據進行的判斷);
  • **andDo:**添加ResultHandler結果處理器,比如調試時打印結果到控制檯(對返回的數據進行的判斷);
  • **andReturn:**最後返回相應的MvcResult;然後進行自定義驗證/進行下一步的異步處理(對返回的數據進行的判斷)。

MockMvcRequestBuilders常用API:

  • MockHttpServletRequestBuilder get(String urlTemplate, Object… - urlVariables):根據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):創建一個從啓動異步處理的請求的MvcResult進行異步分派的RequestBuilder;

MockHttpServletRequestBuilder常用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體內容;

  • MockHttpServletRequestBuilder cookie(Cookie… cookies):指定請求的Cookie;

  • MockHttpServletRequestBuilder locale(Locale locale):指定請求的Locale;

  • MockHttpServletRequestBuilder characterEncoding(String encoding):指定請求字符編碼;

  • MockHttpServletRequestBuilder requestAttr(String name, Object value) :設置請求屬性數據;

  • MockHttpServletRequestBuilder sessionAttr(String name, Object value)/MockHttpServletRequestBuilder - sessionAttrs(Map<string, object=""> sessionAttributes):設置請求session屬性數據;

  • 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) - :指定請求的上下文路徑,必須以“/”開頭,且不能以“/”結尾;

  • MockHttpServletRequestBuilder pathInfo(String pathInfo) :請求的路徑信息,必須以“/”開頭;

  • MockHttpServletRequestBuilder secure(boolean secure):請求是否使用安全通道;

  • MockHttpServletRequestBuilder with(RequestPostProcessor - postProcessor):請求的後處理器,用於自定義一些請求處理的擴展點;

MvcResult

  • MvcResult爲執行完控制器後得到的整個結果,並不僅僅是返回值,其包含了測試時需要的所有信息。

  • MockHttpServletRequest getRequest():得到執行的請求;

  • MockHttpServletResponse getResponse():得到執行後的響應;

  • Object getHandler():得到執行的處理器,一般就是控制器;

  • HandlerInterceptor[] getInterceptors():得到對處理器進行攔截的攔截器;

  • ModelAndView getModelAndView():得到執行後的ModelAndView;

  • Exception getResolvedException():得到HandlerExceptionResolver解析後的異常;

  • FlashMap getFlashMap():得到FlashMap;

  • Object getAsyncResult()/Object getAsyncResult(long timeout):得到異步執行的結果;

結尾

雖然說現在的業務千變萬化,但是如果有時間還是多寫寫單元測試吧。更多的實戰還是要碰到了纔會更瞭解。

日常求贊

好了各位,以上就是這篇文章的全部內容了,能看到這裏的人呀,都是真粉

創作不易,各位的支持和認可,就是我創作的最大動力,我們下篇文章見

六脈神劍 | 文 【原創】如果本篇博客有任何錯誤,請批評指教,不勝感激 !

上面提到了 分佈式頭條項目 回覆 888 獲取 我敢說超過了大部分仔目前的技術範圍維度。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章