2. 问题基于Spring Boot的项目,公司强制要求必须写UT,否则不让提MR,而且要覆盖每一行代码。
3. 解决办法因为要覆盖每一行代码,考虑到有些功能使用到了filter或者interceptor,所以采用在测试类中直接注入
controller类
的方式也满足不了。
例如:@Resource private UserController userController; public void testGetUser(){ userController.getXX(); }
使用MockMvc,可以从头到尾,测试一遍,就类似用户直接使用系统的感觉,帮助开发者覆盖到filter->interceptor->controller->service->dao的每一行代码。
废话不说,直接上代码
4. 工程结构 4.1 工程pom文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.5.11version>
<relativePath/>
parent>
<groupId>com.xywei.springbootgroupId>
<artifactId>springtest-demoartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>springtest-demoname>
<description>Demo project for Spring Boot with testdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
exclude>
excludes>
configuration>
plugin>
plugins>
build>
project>
4.2 MockMvc之Get请求+请求头
4.2.1 controller方法
/**
* GET请求,查询参数+请求头
* 随机返回用户名和密码
*
* @param userId
* @param userToken
* @return
*/
@GetMapping("/getUserById")
public ResponseEntity<BaseResult> getUserById(@RequestParam(value = "user_id", required = true) String userId,
@RequestHeader(value = "user_token") String userToken) {
BaseResult<User> baseResult = new BaseResult<>();
User user = new User(userId, "whoami-" + userId.hashCode(), UUID.randomUUID().toString());
baseResult.setCode(HttpStatus.OK.value());
baseResult.setMessage(HttpStatus.OK.getReasonPhrase());
baseResult.setData(user);
return new ResponseEntity<BaseResult>(baseResult, HttpStatus.OK);
}
4.2.2 MockMvc测试
@Test
public void testGetUserById() {
try {
ResultActions perform = mockMvc.perform(
MockMvcRequestBuilders
.get("/getUserById") // 相当于postman输入请求地址
.param("user_id", "userId:998") // 相当于postman输入查询参数
.header("user_token", "为人民服务")// 相当于postman输入headers信息
);
String result = perform.andExpect(MockMvcResultMatchers.status().isOk())
.andReturn().getResponse().getContentAsString();
ObjectMapper objectMapper = new ObjectMapper();
BaseResult baseResult = objectMapper.readValue(result, BaseResult.class);
Assert.notNull(baseResult.getData(), "expect not empty!");
} catch (Exception e) {
e.printStackTrace();
}
}
4.3 MockMvc之POST请求+表单参数
4.3.1 controller方法
/**
* POST请求,接受表单参数
* 给什么就返回什么,随机生成id
*
* @param username
* @param password
* @return
*/
@PostMapping("/getUserByUsernamePassword")
public ResponseEntity<BaseResult> getUserByUsernamePassword(String username, String password) {
BaseResult<User> baseResult = new BaseResult<>();
User user = new User(UUID.randomUUID().toString(), username, password);
baseResult.setCode(HttpStatus.OK.value());
baseResult.setMessage(HttpStatus.OK.getReasonPhrase());
baseResult.setData(user);
return new ResponseEntity<BaseResult>(baseResult, HttpStatus.OK);
}
4.3.2 MockMvc测试
@Test
public void testGetUserByUsernamePassword() {
try {
ResultActions perform = mockMvc.perform(
MockMvcRequestBuilders
.post("/getUserByUsernamePassword") // 相当于postman输入请求地址
.param("username", "吃了八年的鱼") // 相当于postman输入表单参数
.param("password", "我为群众办实事") // 相当于postman输入表单参数
);
String result = perform
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print())
.andReturn().getResponse().getContentAsString();
Assert.notNull(result, "should be not empty!");
} catch (Exception e) {
e.printStackTrace();
}
}
4.4 MockMvc之POST请求+JSON参数
4.4.1 controller方法
/**
* POST请求,接受JSON数据
* 给什么就返回什么
*
* @param users
* @return
*/
@PostMapping("/insertUser")
public ResponseEntity<BaseResult> insertUser(@RequestBody List<User> users) {
BaseResult<List<User>> baseResult = new BaseResult<>();
baseResult.setCode(HttpStatus.OK.value());
baseResult.setMessage(HttpStatus.OK.getReasonPhrase());
baseResult.setData(users);
return new ResponseEntity<BaseResult>(baseResult, HttpStatus.OK);
}
4.4.2 MockMvc测试
@Test
public void testInsertUser() {
User user = new User(UUID.randomUUID().toString(), "群众第一", "为群众谋福利");
List<User> param = new ArrayList<>();
param.add(user);
try {
String jsonData = new ObjectMapper().writeValueAsString(param);
ResultActions perform = mockMvc.perform(
MockMvcRequestBuilders
.post("/insertUser") // 相当于postman输入请求地址
.contentType(MediaType.APPLICATION_JSON)
.content(jsonData)
);
String result = perform
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print())
.andReturn().getResponse().getContentAsString();
Assert.notNull(result, "should be not empty!");
} catch (Exception e) {
e.printStackTrace();
}
}
4.5 完整的Tests代码
package com.xywei.springboot.springtestdemo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xywei.springboot.springtestdemo.entity.User;
import com.xywei.springboot.springtestdemo.vo.BaseResult;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.util.Assert;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@SpringBootTest
@AutoConfigureMockMvc
public class UserTests {
@Resource
private MockMvc mockMvc;
@Test
public void testGetUserById() {
try {
ResultActions perform = mockMvc.perform(
MockMvcRequestBuilders
.get("/getUserById") // 相当于postman输入请求地址
.param("user_id", "userId:998") // 相当于postman输入查询参数
.header("user_token", "为人民服务")// 相当于postman输入headers信息
);
String result = perform.andExpect(MockMvcResultMatchers.status().isOk())
.andReturn().getResponse().getContentAsString();
ObjectMapper objectMapper = new ObjectMapper();
BaseResult baseResult = objectMapper.readValue(result, BaseResult.class);
Assert.notNull(baseResult.getData(), "expect not empty!");
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void testGetUserByUsernamePassword() {
try {
ResultActions perform = mockMvc.perform(
MockMvcRequestBuilders
.post("/getUserByUsernamePassword") // 相当于postman输入请求地址
.param("username", "吃了八年的鱼") // 相当于postman输入表单参数
.param("password", "我为群众办实事") // 相当于postman输入表单参数
);
String result = perform
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print())
.andReturn().getResponse().getContentAsString();
Assert.notNull(result, "should be not empty!");
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void testInsertUser() {
User user = new User(UUID.randomUUID().toString(), "群众第一", "为群众谋福利");
List<User> param = new ArrayList<>();
param.add(user);
try {
String jsonData = new ObjectMapper().writeValueAsString(param);
ResultActions perform = mockMvc.perform(
MockMvcRequestBuilders
.post("/insertUser") // 相当于postman输入请求地址
.contentType(MediaType.APPLICATION_JSON)
.content(jsonData)
);
String result = perform
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcResultHandlers.print())
.andReturn().getResponse().getContentAsString();
Assert.notNull(result, "should be not empty!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
5 总结
- 已上代码基于所有大佬都有基础的条件,如有不懂,请自行查阅SpringBoot的使用。
- 代码中的Filter和Inteceptor太简单,所以没有给出,请自行配置,更好体验MockMvc。
- 未连接数据库,请自行配置。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)