溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何Spring Boot中使用MockMvc對(duì)象進(jìn)行單元測試

發(fā)布時(shí)間:2020-11-26 16:41:00 來源:億速云 閱讀:269 作者:Leah 欄目:編程語言

這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)碛嘘P(guān)如何Spring Boot中使用MockMvc對(duì)象進(jìn)行單元測試,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

Spring測試框架提供MockMvc對(duì)象,可以在不需要客戶端-服務(wù)端請(qǐng)求的情況下進(jìn)行MVC測試,完全在服務(wù)端這邊就可以執(zhí)行Controller的請(qǐng)求,跟啟動(dòng)了測試服務(wù)器一樣。

測試開始之前需要建立測試環(huán)境,setup方法被@Before修飾。通過MockMvcBuilders工具,使用WebApplicationContext對(duì)象作為參數(shù),創(chuàng)建一個(gè)MockMvc對(duì)象。

MockMvc對(duì)象提供一組工具函數(shù)用來執(zhí)行assert判斷,都是針對(duì)web請(qǐng)求的判斷。這組工具的使用方式是函數(shù)的鏈?zhǔn)秸{(diào)用,允許程序員將多個(gè)測試用例鏈接在一起,并進(jìn)行多個(gè)判斷。在這個(gè)例子中我們用到下面的一些工具函數(shù):

perform(get(...))建立web請(qǐng)求。在我們的第三個(gè)用例中,通過MockMvcRequestBuilder執(zhí)行GET請(qǐng)求。

andExpect(...)可以在perform(...)函數(shù)調(diào)用后多次調(diào)用,表示對(duì)多個(gè)條件的判斷,這個(gè)函數(shù)的參數(shù)類型是ResultMatcher接口,在MockMvcResultMatchers這這個(gè)類中提供了很多返回ResultMatcher接口的工具函數(shù)。這個(gè)函數(shù)使得可以檢測同一個(gè)web請(qǐng)求的多個(gè)方面,包括HTTP響應(yīng)狀態(tài)碼(response status),響應(yīng)的內(nèi)容類型(content type),會(huì)話中存放的值,檢驗(yàn)重定向、model或者h(yuǎn)eader的內(nèi)容等等。這里需要通過第三方庫json-path檢測JSON格式的響應(yīng)數(shù)據(jù):檢查json數(shù)據(jù)包含正確的元素類型和對(duì)應(yīng)的值,例如jsonPath("$.name").value("中文測試")用于檢查在根目錄下有一個(gè)名為name的節(jié)點(diǎn),并且該節(jié)點(diǎn)對(duì)應(yīng)的值是“testuser”。

本文對(duì)rest api的開發(fā)不做詳細(xì)描述,如需了解可以參考 Spring Boot實(shí)戰(zhàn)之Rest接口開發(fā)及數(shù)據(jù)庫基本操作

1、修改pom.xml,添加依賴庫json-path,用于檢測JSON格式的響應(yīng)數(shù)據(jù)

<dependency> 
  <groupId>com.jayway.jsonpath</groupId> 
  <artifactId>json-path</artifactId> 
</dependency>

 2、添加用戶數(shù)據(jù)模型UserInfo.java

package com.xiaofangtech.sunt.bean; 
 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
import javax.persistence.Table; 
import javax.validation.constraints.Size; 
 
@Entity 
@Table(name="t_userinfo") 
public class UserInfo { 
  @Id  
  @GeneratedValue(strategy = GenerationType.AUTO)  
  private Long id; 
  @Size(min=0, max=32) 
  private String name; 
   
  private Integer age; 
  @Size(min=0, max=255) 
  private String address; 
 
  public Long getId() { 
    return id; 
  } 
 
  public void setId(Long id) { 
    this.id = id; 
  } 
 
  public String getName() { 
    return name; 
  } 
 
  public void setName(String name) { 
    this.name = name; 
  } 
 
  public Integer getAge() { 
    return age; 
  } 
 
  public void setAge(Integer age) { 
    this.age = age; 
  } 
 
  public String getAddress() { 
    return address; 
  } 
 
  public void setAddress(String address) { 
    this.address = address; 
  } 
}

3、添加控制器UserController.java,用于實(shí)現(xiàn)對(duì)用戶的增刪改查

package com.xiaofangtech.sunt.controller; 
 
import java.util.List; 
 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.data.jpa.repository.Modifying; 
import org.springframework.web.bind.annotation.RequestBody; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 
import org.springframework.web.bind.annotation.RestController; 
 
import com.xiaofangtech.sunt.bean.UserInfo; 
import com.xiaofangtech.sunt.repository.UserInfoRepository; 
import com.xiaofangtech.sunt.utils.*; 
 
@RestController  
@RequestMapping("user") 
public class UserController { 
  @Autowired  
  private UserInfoRepository userRepositoy; 
   
  /*** 
   * 根據(jù)用戶id,獲取用戶信息 
   * @param id 
   * @return 
   */ 
  @RequestMapping(value="getuser", method=RequestMethod.GET)  
  public Object getUser(Long id)  
  {  
    UserInfo userEntity = userRepositoy.findOne(id);  
    ResultMsg resultMsg = new ResultMsg(ResultStatusCode.OK.getErrcode(), ResultStatusCode.OK.getErrmsg(), userEntity);  
    return resultMsg;  
  } 
   
  /*** 
   * 獲取所有用戶列表 
   * @return 
   */ 
  @RequestMapping(value="getalluser", method=RequestMethod.GET)  
  public Object getUserList() 
  { 
    List<UserInfo> userEntities = (List<UserInfo>) userRepositoy.findAll(); 
    ResultMsg resultMsg = new ResultMsg(ResultStatusCode.OK.getErrcode(), ResultStatusCode.OK.getErrmsg(), userEntities);  
    return resultMsg; 
  } 
   
  /*** 
   * 新增用戶信息 
   * @param userEntity 
   * @return 
   */ 
  @Modifying 
  @RequestMapping(value="adduser", method=RequestMethod.POST) 
  public Object addUser(@RequestBody UserInfo userEntity) 
  { 
    userRepositoy.save(userEntity);  
    ResultMsg resultMsg = new ResultMsg(ResultStatusCode.OK.getErrcode(), ResultStatusCode.OK.getErrmsg(), userEntity);  
    return resultMsg;  
  } 
   
  /*** 
   * 更新用戶信息 
   * @param userEntity 
   * @return 
   */ 
  @Modifying  
  @RequestMapping(value="updateuser", method=RequestMethod.PUT)  
  public Object updateUser(@RequestBody UserInfo userEntity)  
  {  
    UserInfo user = userRepositoy.findOne(userEntity.getId()); 
    if (user != null)  
    {  
      user.setName(userEntity.getName()); 
      user.setAge(userEntity.getAge()); 
      user.setAddress(userEntity.getAddress()); 
      userRepositoy.save(user); 
    } 
    ResultMsg resultMsg = new ResultMsg(ResultStatusCode.OK.getErrcode(), ResultStatusCode.OK.getErrmsg(), user);  
    return resultMsg; 
  } 
   
  /*** 
   * 刪除用戶 
   * @param id 
   * @return 
   */ 
  @Modifying  
  @RequestMapping(value="deleteuser", method=RequestMethod.DELETE)   
  public Object deleteUser(Long id)  
  {  
    try 
    { 
      userRepositoy.delete(id);  
    } 
    catch(Exception exception) 
    { 
       
    } 
    ResultMsg resultMsg = new ResultMsg(ResultStatusCode.OK.getErrcode(), ResultStatusCode.OK.getErrmsg(), null);  
    return resultMsg;  
  }  
}

4、修改測試類,添加對(duì)以上接口進(jìn)行單元測試的測試用例

package com.xiaofangtech.sunt; 
 
import org.junit.Before; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.boot.test.SpringApplicationConfiguration; 
import org.springframework.http.MediaType; 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 
import org.springframework.test.context.web.WebAppConfiguration; 
import org.springframework.test.web.servlet.MockMvc; 
import org.springframework.test.web.servlet.setup.MockMvcBuilders; 
import org.springframework.web.context.WebApplicationContext; 
 
import com.fasterxml.jackson.databind.ObjectMapper; 
import com.xiaofangtech.sunt.bean.UserInfo; 
 
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; 
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; 
import static org.hamcrest.Matchers.*; 
//這是JUnit的注解,通過這個(gè)注解讓SpringJUnit4ClassRunner這個(gè)類提供Spring測試上下文。 
@RunWith(SpringJUnit4ClassRunner.class) 
//這是Spring Boot注解,為了進(jìn)行集成測試,需要通過這個(gè)注解加載和配置Spring應(yīng)用上下 
@SpringApplicationConfiguration(classes = SpringJUnitTestApplication.class) 
@WebAppConfiguration 
public class SpringJUnitTestApplicationTests { 
 
  @Autowired 
  private WebApplicationContext context; 
   
  private MockMvc mockMvc;  
 
  @Before  
  public void setupMockMvc() throws Exception {  
    mockMvc = MockMvcBuilders.webAppContextSetup(context).build();  
  } 
   
   
  /*** 
   * 測試添加用戶接口 
   * @throws Exception 
   */ 
  @Test 
  public void testAddUser() throws Exception 
  { 
    //構(gòu)造添加的用戶信息 
    UserInfo userInfo = new UserInfo(); 
    userInfo.setName("testuser2"); 
    userInfo.setAge(29); 
    userInfo.setAddress("北京"); 
    ObjectMapper mapper = new ObjectMapper(); 
     
    //調(diào)用接口,傳入添加的用戶參數(shù) 
    mockMvc.perform(post("/user/adduser") 
        .contentType(MediaType.APPLICATION_JSON_UTF8) 
        .content(mapper.writeValueAsString(userInfo))) 
    //判斷返回值,是否達(dá)到預(yù)期,測試示例中的返回值的結(jié)構(gòu)如下{"errcode":0,"errmsg":"OK","p2pdata":null} 
    .andExpect(status().isOk()) 
    .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) 
    //使用jsonPath解析返回值,判斷具體的內(nèi)容 
    .andExpect(jsonPath("$.errcode", is(0))) 
    .andExpect(jsonPath("$.p2pdata", notNullValue())) 
    .andExpect(jsonPath("$.p2pdata.id", not(0))) 
    .andExpect(jsonPath("$.p2pdata.name", is("testuser2"))); 
  } 
   
  /*** 
   * 測試更新用戶信息接口 
   * @throws Exception 
   */ 
  @Test 
  public void testUpdateUser() throws Exception 
  { 
    //構(gòu)造添加的用戶信息,更新id為2的用戶的用戶信息 
    UserInfo userInfo = new UserInfo(); 
    userInfo.setId((long)2); 
    userInfo.setName("testuser"); 
    userInfo.setAge(26); 
    userInfo.setAddress("南京"); 
    ObjectMapper mapper = new ObjectMapper(); 
     
    mockMvc.perform(put("/user/updateuser") 
        .contentType(MediaType.APPLICATION_JSON_UTF8) 
        .content(mapper.writeValueAsString(userInfo))) 
    //判斷返回值,是否達(dá)到預(yù)期,測試示例中的返回值的結(jié)構(gòu)如下 
    //{"errcode":0,"errmsg":"OK","p2pdata":null} 
    .andExpect(status().isOk()) 
    .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) 
    .andExpect(jsonPath("$.errcode", is(0))) 
    .andExpect(jsonPath("$.p2pdata", notNullValue())) 
    .andExpect(jsonPath("$.p2pdata.id", is(2))) 
    .andExpect(jsonPath("$.p2pdata.name", is("testuser"))) 
    .andExpect(jsonPath("$.p2pdata.age", is(26))) 
    .andExpect(jsonPath("$.p2pdata.address", is("南京"))); 
  } 
   
  /*** 
   * 測試根據(jù)用戶id獲取用戶信息接口 
   * @throws Exception 
   */ 
  @Test 
  public void testGetUser() throws Exception 
  { 
    mockMvc.perform(get("/user/getuser?id=2")) 
    .andExpect(status().isOk()) 
    .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) 
    .andExpect(jsonPath("$.errcode", is(0))) 
    .andExpect(jsonPath("$.p2pdata", notNullValue())) 
    .andExpect(jsonPath("$.p2pdata.id", is(2))) 
    .andExpect(jsonPath("$.p2pdata.name", is("testuser"))) 
    .andExpect(jsonPath("$.p2pdata.age", is(26))) 
    .andExpect(jsonPath("$.p2pdata.address", is("南京"))); 
  } 
 
  /*** 
   * 測試獲取用戶列表接口 
   * @throws Exception 
   */ 
  @Test 
  public void testGetUsers() throws Exception 
  { 
    mockMvc.perform(get("/user/getalluser")) 
    .andExpect(status().isOk()) 
    .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) 
    .andExpect(jsonPath("$.errcode", is(0))) 
    .andExpect(jsonPath("$.p2pdata", notNullValue())); 
  } 
}

上述就是小編為大家分享的如何Spring Boot中使用MockMvc對(duì)象進(jìn)行單元測試了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI