SpringBoot学习之--单元测试(八)-2

本文介绍使用Spring测试框架提供的MockMvc对象,对Restful API进行单元测试

Spring测试框架提供MockMvc对象,可以在不需要客户端-服务端请求的情况下进行MVC测试,完全在服务端这边就可以执行Controller的请求,跟启动了测试服务器一样。
测试开始之前需要建立测试环境,setup方法被@Before修饰。通过MockMvcBuilders工具,使用WebApplicationContext对象作为参数,创建一个MockMvc对象。

MockMvc对象提供一组工具函数用来执行assert判断,都是针对web请求的判断。这组工具的使用方式是函数的链式调用,允许程序员将多个测试用例链接在一起,并进行多个判断。在这个例子中我们用到下面的一些工具函数:
perform(get(...))建立web请求。在我们的第三个用例中,通过MockMvcRequestBuilder执行GET请求。
andExpect(...)可以在perform(...)函数调用后多次调用,表示对多个条件的判断,这个函数的参数类型是ResultMatcher接口,在MockMvcResultMatchers这这个类中提供了很多返回ResultMatcher接口的工具函数。这个函数使得可以检测同一个web请求的多个方面,包括HTTP响应状态码(response status),响应的内容类型(content type),会话中存放的值,检验重定向、model或者header的内容等等。这里需要通过第三方库json-path检测JSON格式的响应数据:检查json数据包含正确的元素类型和对应的值,例如jsonPath("$.name").value("中文测试")用于检查在根目录下有一个名为name的节点,并且该节点对应的值是“testuser”。


本文对rest api的开发不做详细描述,如需了解可以参考 Spring Boot实战之Rest接口开发及数据库基本操作

1、修改pom.xml,添加依赖库json-path,用于检测JSON格式的响应数据

[html]  view plain  copy
  1. <dependency>  
  2.     <groupId>com.jayway.jsonpath</groupId>  
  3.     <artifactId>json-path</artifactId>  
  4. </dependency>  


2、添加用户数据模型UserInfo.java

[java]  view plain  copy
  1. package com.xiaofangtech.sunt.bean;  
  2.   
  3. import javax.persistence.Entity;  
  4. import javax.persistence.GeneratedValue;  
  5. import javax.persistence.GenerationType;  
  6. import javax.persistence.Id;  
  7. import javax.persistence.Table;  
  8. import javax.validation.constraints.Size;  
  9.   
  10. @Entity  
  11. @Table(name="t_userinfo")  
  12. public class UserInfo {  
  13.     @Id    
  14.     @GeneratedValue(strategy = GenerationType.AUTO)    
  15.     private Long id;  
  16.     @Size(min=0, max=32)  
  17.     private String name;  
  18.       
  19.     private Integer age;  
  20.     @Size(min=0, max=255)  
  21.     private String address;  
  22.   
  23.     public Long getId() {  
  24.         return id;  
  25.     }  
  26.   
  27.     public void setId(Long id) {  
  28.         this.id = id;  
  29.     }  
  30.   
  31.     public String getName() {  
  32.         return name;  
  33.     }  
  34.   
  35.     public void setName(String name) {  
  36.         this.name = name;  
  37.     }  
  38.   
  39.     public Integer getAge() {  
  40.         return age;  
  41.     }  
  42.   
  43.     public void setAge(Integer age) {  
  44.         this.age = age;  
  45.     }  
  46.   
  47.     public String getAddress() {  
  48.         return address;  
  49.     }  
  50.   
  51.     public void setAddress(String address) {  
  52.         this.address = address;  
  53.     }  
  54. }  

3、添加控制器UserController.java,用于实现对用户的增删改查

[java]  view plain  copy
  1. package com.xiaofangtech.sunt.controller;  
  2.   
  3. import java.util.List;  
  4.   
  5. import org.springframework.beans.factory.annotation.Autowired;  
  6. import org.springframework.data.jpa.repository.Modifying;  
  7. import org.springframework.web.bind.annotation.RequestBody;  
  8. import org.springframework.web.bind.annotation.RequestMapping;  
  9. import org.springframework.web.bind.annotation.RequestMethod;  
  10. import org.springframework.web.bind.annotation.RestController;  
  11.   
  12. import com.xiaofangtech.sunt.bean.UserInfo;  
  13. import com.xiaofangtech.sunt.repository.UserInfoRepository;  
  14. import com.xiaofangtech.sunt.utils.*;  
  15.   
  16. @RestController    
  17. @RequestMapping("user")  
  18. public class UserController {  
  19.     @Autowired    
  20.     private UserInfoRepository userRepositoy;  
  21.       
  22.     /*** 
  23.      * 根据用户id,获取用户信息 
  24.      * @param id 
  25.      * @return 
  26.      */  
  27.     @RequestMapping(value="getuser", method=RequestMethod.GET)    
  28.     public Object getUser(Long id)    
  29.     {    
  30.         UserInfo userEntity = userRepositoy.findOne(id);   
  31.         ResultMsg resultMsg = new ResultMsg(ResultStatusCode.OK.getErrcode(), ResultStatusCode.OK.getErrmsg(), userEntity);    
  32.         return resultMsg;    
  33.     }  
  34.       
  35.     /*** 
  36.      * 获取所有用户列表 
  37.      * @return 
  38.      */  
  39.     @RequestMapping(value="getalluser", method=RequestMethod.GET)   
  40.     public Object getUserList()  
  41.     {  
  42.         List<UserInfo> userEntities = (List<UserInfo>) userRepositoy.findAll();  
  43.         ResultMsg resultMsg = new ResultMsg(ResultStatusCode.OK.getErrcode(), ResultStatusCode.OK.getErrmsg(), userEntities);    
  44.         return resultMsg;  
  45.     }  
  46.       
  47.     /*** 
  48.      * 新增用户信息 
  49.      * @param userEntity 
  50.      * @return 
  51.      */  
  52.     @Modifying  
  53.     @RequestMapping(value="adduser", method=RequestMethod.POST)  
  54.     public Object addUser(@RequestBody UserInfo userEntity)  
  55.     {  
  56.         userRepositoy.save(userEntity);    
  57.         ResultMsg resultMsg = new ResultMsg(ResultStatusCode.OK.getErrcode(), ResultStatusCode.OK.getErrmsg(), userEntity);    
  58.         return resultMsg;   
  59.     }  
  60.       
  61.     /*** 
  62.      * 更新用户信息 
  63.      * @param userEntity 
  64.      * @return 
  65.      */  
  66.     @Modifying    
  67.     @RequestMapping(value="updateuser", method=RequestMethod.PUT)    
  68.     public Object updateUser(@RequestBody UserInfo userEntity)    
  69.     {    
  70.         UserInfo user = userRepositoy.findOne(userEntity.getId());  
  71.         if (user != null)    
  72.         {    
  73.             user.setName(userEntity.getName());  
  74.             user.setAge(userEntity.getAge());  
  75.             user.setAddress(userEntity.getAddress());  
  76.             userRepositoy.save(user);  
  77.         }  
  78.         ResultMsg resultMsg = new ResultMsg(ResultStatusCode.OK.getErrcode(), ResultStatusCode.OK.getErrmsg(), user);    
  79.         return resultMsg;  
  80.     }  
  81.       
  82.     /*** 
  83.      * 删除用户 
  84.      * @param id 
  85.      * @return 
  86.      */  
  87.     @Modifying    
  88.     @RequestMapping(value="deleteuser", method=RequestMethod.DELETE)     
  89.     public Object deleteUser(Long id)    
  90.     {    
  91.         try  
  92.         {  
  93.             userRepositoy.delete(id);   
  94.         }  
  95.         catch(Exception exception)  
  96.         {  
  97.               
  98.         }  
  99.         ResultMsg resultMsg = new ResultMsg(ResultStatusCode.OK.getErrcode(), ResultStatusCode.OK.getErrmsg(), null);    
  100.         return resultMsg;    
  101.     }   
  102. }  

4、修改测试类,添加对以上接口进行单元测试的测试用例 

如果你用的SpringBoot是1.4.0之后的话,所用的注解稍有不同。你需要@SpringApplicationConfiguration和@WebAppConfiguration换成@SpringBootTest注解
@RunWith @SpringBootTest   @ActiveProfiles 注解都是@Inherited属性的因此可以被子类继承,所以只需要在BaseTest中配置就好了,
* 其他测试类通过继承BaseTest来获取相应配置属性

[java]  view plain  copy
  1. package com.xiaofangtech.sunt;  
  2.   
  3. import org.junit.Before;  
  4. import org.junit.Test;  
  5. import org.junit.runner.RunWith;  
  6. import org.springframework.beans.factory.annotation.Autowired;  
  7. import org.springframework.boot.test.SpringApplicationConfiguration;  
  8. import org.springframework.http.MediaType;  
  9. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  
  10. import org.springframework.test.context.web.WebAppConfiguration;  
  11. import org.springframework.test.web.servlet.MockMvc;  
  12. import org.springframework.test.web.servlet.setup.MockMvcBuilders;  
  13. import org.springframework.web.context.WebApplicationContext;  
  14.   
  15. import com.fasterxml.jackson.databind.ObjectMapper;  
  16. import com.xiaofangtech.sunt.bean.UserInfo;  
  17.   
  18. import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;  
  19. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;  
  20. import static org.hamcrest.Matchers.*;  
  21. //这是JUnit的注解,通过这个注解让SpringJUnit4ClassRunner这个类提供Spring测试上下文。  
  22. @RunWith(SpringJUnit4ClassRunner.class)  
  23. //这是Spring Boot注解,为了进行集成测试,需要通过这个注解加载和配置Spring应用上下  
  24. @SpringApplicationConfiguration(classes = SpringJUnitTestApplication.class)  
  25. @WebAppConfiguration 
  26. //指定当前活动状态的profile 
  27. @ActiveProfiles("local")
  28. public class SpringJUnitTestApplicationTests {  
  29.   
  30.     @Autowired  
  31.     private WebApplicationContext context;  
  32.       
  33.     private MockMvc mockMvc;   
  34.   
  35.     @Before   
  36.     public void setupMockMvc() throws Exception {   
  37.         mockMvc = MockMvcBuilders.webAppContextSetup(context).build();   
  38.     }  
  39.       
  40.       
  41.     /*** 
  42.      * 测试添加用户接口 
  43.      * @throws Exception 
  44.      */  
  45.     @Test  
  46.     public void testAddUser() throws Exception  
  47.     {  
  48.         //构造添加的用户信息  
  49.         UserInfo userInfo = new UserInfo();  
  50.         userInfo.setName("testuser2");  
  51.         userInfo.setAge(29);  
  52.         userInfo.setAddress("北京");  
  53.         ObjectMapper mapper = new ObjectMapper();  
  54.           
  55.         //调用接口,传入添加的用户参数  
  56.         mockMvc.perform(post("/user/adduser")  
  57.                 .contentType(MediaType.APPLICATION_JSON_UTF8)  
  58.                 .content(mapper.writeValueAsString(userInfo)))  
  59.         //判断返回值,是否达到预期,测试示例中的返回值的结构如下{"errcode":0,"errmsg":"OK","p2pdata":null}  
  60.         .andExpect(status().isOk())  
  61.         .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))  
  62.         //使用jsonPath解析返回值,判断具体的内容  
  63.         .andExpect(jsonPath("$.errcode", is(0)))  
  64.         .andExpect(jsonPath("$.p2pdata", notNullValue()))  
  65.         .andExpect(jsonPath("$.p2pdata.id", not(0)))  
  66.         .andExpect(jsonPath("$.p2pdata.name", is("testuser2")));  
  67.     }  
  68.       
  69.     /*** 
  70.      * 测试更新用户信息接口 
  71.      * @throws Exception 
  72.      */  
  73.     @Test  
  74.     public void testUpdateUser() throws Exception  
  75.     {  
  76.         //构造添加的用户信息,更新id为2的用户的用户信息  
  77.         UserInfo userInfo = new UserInfo();  
  78.         userInfo.setId((long)2);  
  79.         userInfo.setName("testuser");  
  80.         userInfo.setAge(26);  
  81.         userInfo.setAddress("南京");  
  82.         ObjectMapper mapper = new ObjectMapper();  
  83.           
  84.         mockMvc.perform(put("/user/updateuser")  
  85.                 .contentType(MediaType.APPLICATION_JSON_UTF8)  
  86.                 .content(mapper.writeValueAsString(userInfo)))  
  87.         //判断返回值,是否达到预期,测试示例中的返回值的结构如下  
  88.         //{"errcode":0,"errmsg":"OK","p2pdata":null}  
  89.         .andExpect(status().isOk())  
  90.         .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))  
  91.         .andExpect(jsonPath("$.errcode", is(0)))  
  92.         .andExpect(jsonPath("$.p2pdata", notNullValue()))  
  93.         .andExpect(jsonPath("$.p2pdata.id", is(2)))  
  94.         .andExpect(jsonPath("$.p2pdata.name", is("testuser")))  
  95.         .andExpect(jsonPath("$.p2pdata.age", is(26)))  
  96.         .andExpect(jsonPath("$.p2pdata.address", is("南京")));  
  97.     }  
  98.       
  99.     /*** 
  100.      * 测试根据用户id获取用户信息接口 
  101.      * @throws Exception 
  102.      */  
  103.     @Test  
  104.     public void testGetUser() throws Exception  
  105.     {  
  106.         mockMvc.perform(get("/user/getuser?id=2"))  
  107.         .andExpect(status().isOk())  
  108.         .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))  
  109.         .andExpect(jsonPath("$.errcode", is(0)))  
  110.         .andExpect(jsonPath("$.p2pdata", notNullValue()))  
  111.         .andExpect(jsonPath("$.p2pdata.id", is(2)))  
  112.         .andExpect(jsonPath("$.p2pdata.name", is("testuser")))  
  113.         .andExpect(jsonPath("$.p2pdata.age", is(26)))  
  114.         .andExpect(jsonPath("$.p2pdata.address", is("南京")));  
  115.     }  
  116.   
  117.     /*** 
  118.      * 测试获取用户列表接口 
  119.      * @throws Exception 
  120.      */  
  121.     @Test  
  122.     public void testGetUsers() throws Exception  
  123.     {  
  124.         mockMvc.perform(get("/user/getalluser"))  
  125.         .andExpect(status().isOk())  
  126.         .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))  
  127.         .andExpect(jsonPath("$.errcode", is(0)))  
  128.         .andExpect(jsonPath("$.p2pdata", notNullValue()));  
  129.     }  
  130. }  

5、运行测试,执行JUnit Test



一共执行4个测试用例,全都通过

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值