Spring Boot 單元測試

一、使用mock進行單元測試

Spring框架提供了MockMvc對象,可以在服務端完成對Controller的啟動。測試開始之前需要建立測試環境,setup方法被@Before修飾。通過MockMvcBuilders工具,使用WebApplicationContext對象作為參數,創建一個MockMvc對象。
示例:

@RunWith(SpringRunner.class)
//這里的CodedictCustomApplication是springboot的啟動類名
@SpringBootTest(classes = CodedictCustomApplication.class)
public class CodeDictControllerTest {

  @Autowired
  private WebApplicationContext wac;

  private MockMvc mvc;

  @Before
  public void setupMockMvc(){
    //初始化MockMvc對象
    mvc = MockMvcBuilders.webAppContextSetup(wac).build();
  }

  /**
   * mockMvc.perform執行一個請求
   * MockMvcRequestBuilders.get(“/user/1”)構造一個請求,Post請求就用.post方法
   * contentType(MediaType.APPLICATION_JSON_UTF8)代表發送端發送的數據格式是application/json;charset=UTF-8
   * accept(MediaType.APPLICATION_JSON_UTF8)代表客戶端希望接受的數據類型為application/json;charset=UTF-8
   * ResultActions.andExpect添加執行完成后的斷言
   * ResultActions.andExpect(MockMvcResultMatchers.status().isOk())方法看請求的狀態響應碼是否為200如果不是則拋異常,測試不通過
   * ResultActions.andExpect(MockMvcResultMatchers.jsonPath("$.showValue").value("證件類型")),這里jsonPath用來獲取showValue字段比對是否為證件類型,不是就測試不通過
   * ResultActions.andDo添加一個結果處理器,表示要對結果做點什么事情,比如此處使用MockMvcResultHandlers.print()輸出整個響應結果信息
   * @throws Exception
   */
  @Test
  public void getAllCatalog() throws Exception {
    mvc.perform(MockMvcRequestBuilders.get("/getAllCatalog")
            .accept(MediaType.APPLICATION_JSON_UTF8)
            .contentType(MediaType.APPLICATION_JSON_UTF8)
    )
    .andExpect(MockMvcResultMatchers.status().isOk())
    .andDo(MockMvcResultHandlers.print());

  }

  @Test
  public void getItem() throws Exception {
    mvc.perform(MockMvcRequestBuilders.get("/getItem")
            .param("rid","ZJLX")
            .accept(MediaType.APPLICATION_JSON_UTF8)
            .contentType(MediaType.APPLICATION_JSON_UTF8)
    )
    .andExpect(MockMvcResultMatchers.status().isOk())
    .andExpect(MockMvcResultMatchers.jsonPath("$.showValue").value("證件類型"))
    .andExpect(MockMvcResultMatchers.jsonPath("$.catalogId").value("#"))
    .andDo(MockMvcResultHandlers.print());
  }

  @Test
  // 單元測試的時候如果不想造成垃圾數據,可以開啟事物功能,記在方法或者類頭部添加@Transactional注解即可
  @Transactional
  public void modifyItem()throws Exception{
    mvc.perform(MockMvcRequestBuilders.get("/modifyItem")
            .param("rid","ZJLX")
            .param("code","ZJLX")
            .param("catalogId","#")
            .param("sortValue","1")
            .param("showValue","證件")
            .accept(MediaType.APPLICATION_JSON_UTF8)
            .contentType(MediaType.APPLICATION_JSON_UTF8)
    )
    .andExpect(MockMvcResultMatchers.status().isOk())
    .andDo(MockMvcResultHandlers.print());

    mvc.perform(MockMvcRequestBuilders.get("/getItem")
            .param("rid","ZJLX")
            .accept(MediaType.APPLICATION_JSON_UTF8)
            .contentType(MediaType.APPLICATION_JSON_UTF8)
    )
    .andExpect(MockMvcResultMatchers.status().isOk())
    .andExpect(MockMvcResultMatchers.jsonPath("$.showValue").value("證件"))
    .andExpect(MockMvcResultMatchers.jsonPath("$.sortValue").value("1"))
    .andDo(MockMvcResultHandlers.print());
  }
}

二、新斷言assertThat使用

JUnit 4.4 結合 Hamcrest 提供了一個全新的斷言語法——assertThat。程序員可以只使用 assertThat 一個斷言語句,結合 Hamcrest 提供的匹配符,就可以表達全部的測試思想,我們引入的版本是Junit4.12所以支持assertThat。
基本的語法:

assertThat( [value], [matcher statement] );
  • value:是接下來想要測試的變量值;
  • matcher statement:是使用 Hamcrest 匹配符來表達的對前面變量所期望的值的聲明,如果 value 值與 matcher statement 所表達的期望值相符,則測試成功,否則測試失敗。

示例:

@Test
  public void assertThatUse(){
    //1.使用匹配符 Matcher 和不使用之間的比較
    // 想判斷某個字符串 s 是否含有子字符串 "developer" 或 "Works" 中間的一個
    // JUnit 4.4 以前的版本:assertTrue(s.indexOf("developer")>-1||s.indexOf("Works")>-1 );
    // JUnit 4.4:
    assertThat("s",anyOf(containsString("developer"), containsString("Works")));
    // 匹配符 anyOf 表示任何一個條件滿足則成立,類似于邏輯或 "||", 匹配符 containsString 表示是否含有參數子
    // 字符串,文章接下來會對匹配符進行具體介紹

    //2.Matcher 匹配符聯合使用
    // 聯合匹配符not和equalTo表示“不等于”
    assertThat( "s", not( equalTo( "developer" )));
    // 聯合匹配符not和containsString表示“不包含子字符串”
    assertThat( "s", not( containsString( "Works")));
    // 聯合匹配符anyOf和containsString表示“包含任何一個子字符串”
    assertThat("s", anyOf(containsString("developer"), containsString("Works")));


    //3.默認提供一些可讀的描述性錯誤信息
    String s = "hello world!";
    assertThat( s, anyOf( containsString("developer"), containsString("Works") ) );
    // 如果出錯后,系統會自動拋出以下提示信息:
    // java.lang.AssertionError:
    // Expected: (a string containing "developer" or a string containing "Works")
    // but: was "s"
    // Expected :(a string containing "developer" or a string containing "Works")
  }

其它使用示例:

字符相關匹配符
/**equalTo匹配符斷言被測的testedValue等于expectedValue,
* equalTo可以斷言數值之間,字符串之間和對象之間是否相等,相當于Object的equals方法
*/
assertThat(testedValue, equalTo(expectedValue));
/**equalToIgnoringCase匹配符斷言被測的字符串testedString
*在忽略大小寫的情況下等于expectedString
*/
assertThat(testedString, equalToIgnoringCase(expectedString));
/**equalToIgnoringWhiteSpace匹配符斷言被測的字符串testedString
*在忽略頭尾的任意個空格的情況下等于expectedString,
*注意:字符串中的空格不能被忽略
*/
assertThat(testedString, equalToIgnoringWhiteSpace(expectedString);
/**containsString匹配符斷言被測的字符串testedString包含子字符串subString**/
assertThat(testedString, containsString(subString) );
/**endsWith匹配符斷言被測的字符串testedString以子字符串suffix結尾*/
assertThat(testedString, endsWith(suffix));
/**startsWith匹配符斷言被測的字符串testedString以子字符串prefix開始*/
assertThat(testedString, startsWith(prefix));
一般匹配符
/**nullValue()匹配符斷言被測object的值為null*/
assertThat(object,nullValue());
/**notNullValue()匹配符斷言被測object的值不為null*/
assertThat(object,notNullValue());
/**is匹配符斷言被測的object等于后面給出匹配表達式*/
assertThat(testedString, is(equalTo(expectedValue)));
/**is匹配符簡寫應用之一,is(equalTo(x))的簡寫,斷言testedValue等于expectedValue*/
assertThat(testedValue, is(expectedValue));
/**is匹配符簡寫應用之二,is(instanceOf(SomeClass.class))的簡寫,
*斷言testedObject為Cheddar的實例
*/
assertThat(testedObject, is(Cheddar.class));
/**not匹配符和is匹配符正好相反,斷言被測的object不等于后面給出的object*/
assertThat(testedString, not(expectedString));
/**allOf匹配符斷言符合所有條件,相當于“與”(&&)*/
assertThat(testedNumber, allOf( greaterThan(8), lessThan(16) ) );
/**anyOf匹配符斷言符合條件之一,相當于“或”(||)*/
assertThat(testedNumber, anyOf( greaterThan(16), lessThan(8) ) );
數值相關匹配符
/**closeTo匹配符斷言被測的浮點型數testedDouble在20.0?à0.5范圍之內*/
assertThat(testedDouble, closeTo( 20.0, 0.5 ));
/**greaterThan匹配符斷言被測的數值testedNumber大于16.0*/
assertThat(testedNumber, greaterThan(16.0));
/** lessThan匹配符斷言被測的數值testedNumber小于16.0*/
assertThat(testedNumber, lessThan (16.0));
/** greaterThanOrEqualTo匹配符斷言被測的數值testedNumber大于等于16.0*/
assertThat(testedNumber, greaterThanOrEqualTo (16.0));
/** lessThanOrEqualTo匹配符斷言被測的testedNumber小于等于16.0*/
assertThat(testedNumber, lessThanOrEqualTo (16.0));
集合相關匹配符
/**hasEntry匹配符斷言被測的Map對象mapObject含有一個鍵值為"key"對應元素值為"value"的Entry項*/
assertThat(mapObject, hasEntry("key", "value" ) );
/**hasItem匹配符表明被測的迭代對象iterableObject含有元素element項則測試通過*/
assertThat(iterableObject, hasItem (element));
/** hasKey匹配符斷言被測的Map對象mapObject含有鍵值“key”*/
assertThat(mapObject, hasKey ("key"));
/** hasValue匹配符斷言被測的Map對象mapObject含有元素值value*/
assertThat(mapObject, hasValue(value));
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 前言 這次來介紹下Spring Boot中對單元測試的整合使用,本篇會通過以下4點來介紹,基本滿足日常需求 Ser...
    嘟爺MD閱讀 7,093評論 14 177
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,890評論 18 139
  • 單元測試對于開發人員來說是非常熟悉的,我們每天的工作也都是圍繞著開發與測試進行的,在最早的時候測試都是采用工具De...
    OzanShareing閱讀 4,777評論 0 1
  • 看朋友圈的時候,看到剛進公司的時候挺照顧我的默默姐說:讀的書、走的路、見的人、經的事越多,才越容易發覺自己...
    鳶尾花的徽章微涼閱讀 2,104評論 3 2
  • 這是我寫的第一封情書吧。自你從遙遠的地方來到我的身旁,走進了我的生活中;從陌生到熟悉,從相知到相愛。一步一個腳印,...
    劉陽as閱讀 168評論 0 0