服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - 详解Spring Boot实战之单元测试

详解Spring Boot实战之单元测试

2020-12-02 13:39sun_t89 Java教程

本篇文章主要介绍了详解Spring Boot实战之单元测试,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

本文介绍使用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格式的响应数据

?
1
2
3
4
<dependency>
  <groupId>com.jayway.jsonpath</groupId>
  <artifactId>json-path</artifactId>
</dependency>

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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,用于实现对用户的增删改查

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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;
   
  /***
   * 根据用户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、修改测试类,添加对以上接口进行单元测试的测试用例

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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的注解,通过这个注解让SpringJUnit4ClassRunner这个类提供Spring测试上下文。
@RunWith(SpringJUnit4ClassRunner.class)
//这是Spring Boot注解,为了进行集成测试,需要通过这个注解加载和配置Spring应用上下
@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
  {
    //构造添加的用户信息
    UserInfo userInfo = new UserInfo();
    userInfo.setName("testuser2");
    userInfo.setAge(29);
    userInfo.setAddress("北京");
    ObjectMapper mapper = new ObjectMapper();
     
    //调用接口,传入添加的用户参数
    mockMvc.perform(post("/user/adduser")
        .contentType(MediaType.APPLICATION_JSON_UTF8)
        .content(mapper.writeValueAsString(userInfo)))
    //判断返回值,是否达到预期,测试示例中的返回值的结构如下{"errcode":0,"errmsg":"OK","p2pdata":null}
    .andExpect(status().isOk())
    .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
    //使用jsonPath解析返回值,判断具体的内容
    .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
  {
    //构造添加的用户信息,更新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)))
    //判断返回值,是否达到预期,测试示例中的返回值的结构如下
    //{"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("南京")));
  }
   
  /***
   * 测试根据用户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()));
  }
}

5、运行测试,执行JUnit Test

详解Spring Boot实战之单元测试

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

详解Spring Boot实战之单元测试

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:http://blog.csdn.net/sun_t89/article/details/52185952

延伸 · 阅读

精彩推荐