发布时间:2023-06-13 10:00
对模块进行集成测试时,希望能够通过输入URL对Controller进行测试,如果通过启动服务器,建立http client进行测试,这样会使得测试变得很麻烦,比如,启动速度慢,测试验证不方便,依赖网络环境等
MockMvc实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,这样可以使得测试速度快、不依赖网络环境,而且提供了一套验证的工具,这样可以使得请求的验证统一而且很方便
这里是完整的测试案例:包含Junit5以及Mockmvc
package com.uncle.junittest.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @author
* @date 2022-01-27 上午10:30
**/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
/**
* 序列号
*/
private static final long serialVersionUID = -4449140937612137858L;
/**
* 用户id
*/
private String id;
/**
* 昵称
*/
private String fullName;
/**
* 用户名
*/
private String userName;
/**
* 密码
*/
private String password;
/**
* 年龄
*/
private Integer age;
/**
* 性别
*/
private String sex;
}
package com.uncle.junittest.mapper;
import com.uncle.junittest.bean.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
/**
* @author
* @date 2022-01-27 下午3:30
**/
@Repository
public interface UserMapper {
/**
* 增加用户的方法
*
* @param user 用户信息
* @return 增加成功返回:1;否则返回:0
*/
@Insert(\"insert into user values (#{id},#{fullName},#{userName},#{password},#{age},#{sex})\")
int saveUser(User user);
/**
* 根据id查询用户信息
*
* @param id 用户id
* @return 用户信息
*/
@Select(\"select * from user where id = #{id}\")
User getUser(String id);
}
package com.uncle.junittest.service;
import com.uncle.junittest.bean.User;
import org.apache.ibatis.annotations.Select;
/**
* @author
* @date 2022-01-27 下午3:29
**/
public interface UserService {
/**
* 增加用户的方法
* @param user 用户信息
* @return 增加成功返回:1;否则返回:0
*/
int saveUser(User user);
/**
* 根据id查询用户信息
* @param id 用户id
* @return 用户信息
*/
User getUser(String id);
}
package com.uncle.junittest.service.impl;
import com.uncle.junittest.bean.User;
import com.uncle.junittest.mapper.UserMapper;
import com.uncle.junittest.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @author
* @date 2022-01-27 下午3:29
**/
@Service
public class UserServiceImpl implements UserService {
/**
* UserMapper对象
*/
@Autowired
private UserMapper userMapper;
/**
* 增加用户的方法
* @param user 用户信息
* @return 增加成功返回:1;否则返回:0
*/
@Override
public int saveUser(User user) { return userMapper.saveUser(user); }
/**
* 根据id查询用户信息
* @param id 用户id
* @return 用户信息
*/
@Override
public User getUser(String id) {
return userMapper.getUser(id);
}
}
package com.uncle.junittest.controller;
import com.uncle.junittest.bean.User;
import com.uncle.junittest.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* @author
* @date 2022-01-27 下午3:29
**/
@RequestMapping(\"/test\")
@RestController
public class UserController {
/**
* UserService对象
*/
@Autowired
private UserService userService;
/**
* 新增用户
* @param user User
* @return String
*/
@PostMapping(\"/saveUser\")
public String saveUser(@RequestBody User user) {
int i = userService.saveUser(user);
return i == 1 ? user.toString() : \"新增用户失败\";
}
/**
* 获取用户信息
*
* @return String
*/
@GetMapping(\"/getUser/{id}\")
public String getUser(@PathVariable(value = \"id\") String id) {
User user = userService.getUser(id);
return user.toString();
}
}
package com.uncle.junittest;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan(\"com.uncle.junittest.mapper\")
public class JunitTestApplication {
public static void main(String[] args) {
SpringApplication.run(JunitTestApplication.class, args);
}
}
spring:
datasource:
username: root
password:
url: jdbc:mysql://@rm-2ze44u6e2z7t924t0xo.mysql.rds.aliyuncs.com:3306/
server:
port: 80
mybatis:
configuration:
map-underscore-to-camel-case: true
package com.uncle.junittest.controller;
import com.alibaba.fastjson.JSON;
import com.uncle.junittest.bean.User;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import static org.junit.jupiter.api.Assertions.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
/**
* 用户测试类
*
* @AutoConfigureMockMvc:该注解将会自动配置mockMvc的单元测试
*/
@DisplayName(value = \"用户测试类\")
@Slf4j
@AutoConfigureMockMvc
@SpringBootTest
class UserControllerTest {
/**
* 每个单元测试之前都要执行
*/
@BeforeEach
void testBeforeEach() {
log.info(\"测试要开始了!\");
}
/**
* 每个单元测试之后都要执行
*/
@AfterEach
void testAfterEach() {
log.info(\"测试结束了!\");
}
/**
* 在所有测试之前执行
*/
@BeforeAll
static void testBeforeAll() {
log.info(\"要测试所有测试了!\");
}
/**
* 在所有测试之后执行
*/
@AfterAll
static void testAfterAll() {
log.info(\"所有测试测试完了!\");
}
/**
* mockmvc
*/
@Autowired
MockMvc mockMvc;
/**
* 新增用户接口测试
*
* @Disabled:该注解标识着不需要启动测试
* @Transactional:事物回滚
*/
@Disabled
@DisplayName(\"新增用户接口测试\")
@Transactional
@Test
void saveUser() throws Exception {
// 请求地址
String urlTemplate = \"/test/saveUser\";
/* 请求头集合 */
HttpHeaders headers = new HttpHeaders();
headers.add(\"header1\", \"header1\");
headers.add(\"header2\", \"header2\");
/* 参数体 */
String uuid = UUID.randomUUID().toString();
User user = new User();
user.setId(\"4\");
user.setFullName(\"copico\");
user.setUserName(\"kebike\");
user.setPassword(\"123456\");
user.setAge(19);
user.setSex(\"女\");
// 转换成json对象
String jsonString = JSON.toJSONString(user);
// 请求
RequestBuilder request = MockMvcRequestBuilders
// post请求
.post(urlTemplate)
// 数据类型
.contentType(MediaType.APPLICATION_JSON)
// 请求头
.headers(headers)
// 请求体
.content(jsonString);
MvcResult mvcResult = mockMvc.perform(request)
// 打印日志
.andDo(print())
// 获取返回值
.andReturn();
// 从返回值获取状态码
int status = mvcResult.getResponse().getStatus();
//从返回值获取响应的内容
String contentAsString = mvcResult.getResponse().getContentAsString();
// 断言
assertAll(\"heading\",
() -> assertEquals(200, status, \"保存失败\"),
() -> assertEquals(user.toString(), contentAsString, \"数据保存失败\"));
}
/**
* 获取用户接口测试
*/
@DisplayName(\"获取用户接口测试\")
@Test
void getUser() throws Exception {
// 预期结果
User user = new User(\"1\",
\"小软\",
\"neusoft\",
\"123456\",null,null);
// 请求地址
String urlTemplate = \"/test/getUser/1\";
/* 请求头集合 */
HttpHeaders headers = new HttpHeaders();
headers.add(\"headers1\", \"headers1\");
headers.add(\"headers2\", \"headers2\");
LinkedMultiValueMap<String,String> linkedMultiValueMap = new LinkedMultiValueMap();
linkedMultiValueMap.add(\"params1\", \"params1\");
linkedMultiValueMap.add(\"params2\", \"params2\");
// 请求
RequestBuilder request = MockMvcRequestBuilders
// post请求
.get(urlTemplate)
// 数据类型
.contentType(MediaType.APPLICATION_JSON)
// 请求头
.header(\"header1\",\"header1\")
.headers(headers)
// 请求参数
.param(\"param1\",\"param2\")
.params(linkedMultiValueMap);
MvcResult mvcResult = mockMvc.perform(request)
// 打印日志
.andDo(print())
// 获取返回值
.andReturn();
// 从返回值获取状态码
int status = mvcResult.getResponse().getStatus();
//从返回值获取响应的内容
String contentAsString = mvcResult.getResponse().getContentAsString();
// 断言
assertAll(\"heading\",
() -> assertEquals(200, status, \"用户信息获取失败\"),
() -> assertEquals(user.toString(), contentAsString, \"数据不一致,获取失败\"));
}
/**
*
* 规定方法的超时时间
* 超出时间测试异常
* @throws InterruptedException
*/
@DisplayName(value = \"超出时间测试\")
@Timeout(value = 500,unit = TimeUnit.MILLISECONDS)
@Test
void testTimeout() throws InterruptedException {
Thread.sleep(1000);
}
/**
* 重复测试n次
*/
@RepeatedTest(value = 2)
void repeatedTest() {
assertArrayEquals(new int[]{1, 2}, new int[]{1, 2});
}
}
<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.3.9.RELEASEversion>
<relativePath/>
parent>
<groupId>com.unclegroupId>
<artifactId>junit-testartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>junit-testname>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.75version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>2.2.1version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
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>
人工智能专业术语:物体识别、卷积神经网络、YOLO分别都是什么?
python人工智能tensorflow常见损失函数LOSS汇总
MindSpore报错 ValueError: Minimum inputs size 0 does not match...
在centos docker中封装flask应用,并使用命令和dockerfile两种方式制作镜像实战
[vscode]代码规范ESLint + Prettier 在vue项目中的使用和冲突解决[完美解决]
【八大排序④】归并排序、不基于比较的排序(计数排序、基数排序、桶排序)
强的离谱!串烧70+个Transformer模型,涵盖CV、NLP、金融、隐私计算...
Android 面试题:为什么 Activity 都重建了 ViewModel 还存在?—— Jetpack 系列(3)