Java单元测试使用mock【转载】

article/2025/9/10 23:34:18

1、什么是Mock?

mock是在测试过程中,对于一些不容易构造/获取的对象,创建一个mock对象来模拟对象的行为。比如说你需要调用B服务,可是B服务还没有开发完成,那么你就可以将调用B服务的那部分给Mock掉,并编写你想要的返回结果。 Mock有很多的实现框架,例如Mockito、EasyMock、Jmockit、PowerMock、Spock等等,SpringBoot默认的Mock框架是Mockito,和junit一样,只需要依赖spring-boot-starter-test就可以了。本文代码基于jdk8、junit5、Mockito3

1.1、 Mockito中文文档

Mockito是mocking框架,它让你用简洁的API做测试。而且Mockito简单易学,它可读性强和验证语法简洁。Mockito是GitHub上使用最广泛的Mock框架,并与JUnit结合使用.Mockito框架可以创建和配置mock对象.使用Mockito简化了具有外部依赖的类的测试开发! Mockito具体使用方法见文档https://github.com/hehonghui/mockito-doc-zh#0

1.2、Mockito基本使用方法简介

1)、静态导入会使代码更简洁

import static org.mockito.Mockito.*;

举例:

//创建mock对象,mock一个List接口
List mockedList = mock(List.class);
//如果不使用静态导入,则必须使用Mockito调用
List mockList = Mockito.mock(List.class);

2)、验证某些行为

//你可以mock一个具体的类型,而不仅是接口
LinkedList mockedList = mock(LinkedList.class);mockedList.add("one");//验证
verify(mockedList).add("one");

一旦mock对象被创建了,mock对象会记住所有的交互。然后你就可能选择性的验证你感兴趣的交互。

3)、如何做一些测试桩

//测试桩
when(mockedList.get(0)).thenReturn("first");
when(mockedList.get(1)).thenThrow(new RuntimeException());

当调用mockList.get(0)的时候,返回first
当调用mockList.get(1)的时候,抛出一个运行时异常

4)、其他使用见上面文档

2、MockMVC基于RESTful风格的测试

对于前后端分离的项目而言,无法直接从前端静态代码中测试接口的正确性,因此可以通过MockMVC来模拟HTTP请求。基于RESTful风格的SpringMVC的测试,我们可以测试完整的Spring MVC流程,即从URL请求到控制器处理,再到视图渲染都可以测试。

2.1、初始化MockMvc对象

@Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;//在每个测试方法执行之前都初始化MockMvc对象
@BeforeEach
public void setupMockMvc() {mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}

2.2、完成一些接口的测试

1)、尝试测试一个不存在的请求 /user/1

/*** @DisplayName 自定义测试方法展示的名称* @throws Exception*/
@DisplayName("测试根据Id获取User")
@Test
void contextLoads() throws Exception {//perform,执行一个RequestBuilders请求,会自动执行SpringMVC的流程并映射到相应的控制器执行处理mockMvc.perform(MockMvcRequestBuilders//构造一个get请求.get("/user/1")//请求类型 json.contentType(MediaType.APPLICATION_JSON))// 期待返回的状态码是4XX,因为我们并没有写/user/{id}的get接口.andExpect(MockMvcResultMatchers.status().is4xxClientError());}

展示结果:
在这里插入图片描述

2)、在Controller中完成 /user/{id}

/*** id:\\d+只匹配数字* @param id* @return*/
@GetMapping("/user/{id:\\d+}")
public User getUserById(@PathVariable Long id) {return userService.getById(id);
}

修改一下测试类:期待返回的结果是200

@Test
void getUserById() throws Exception {//perform,执行一个RequestBuilders请求,会自动执行SpringMVC的流程并映射到相应的控制器执行处理mockMvc.perform(MockMvcRequestBuilders//构造一个get请求.get("/user/1")//请求类型 json.contentType(MediaType.APPLICATION_JSON))// 期望的结果状态 200.andExpect(MockMvcResultMatchers.status().isOk());
}

结果展示:
在这里插入图片描述

3)、我们可以把结果打印到控制台

// 期望的结果状态 200
.andExpect(MockMvcResultMatchers.status().isOk())
//添加ResultHandler结果处理器,比如调试时 打印结果(print方法)到控制台
.andDo(MockMvcResultHandlers.print());

运行结果:可以看到并没有返回结果
在这里插入图片描述

4)、结合Mockito构建自定义返回结果

这里就用到了Mockito的应用场景,userService.getById并没有返回结果,但是我们的测试并不关心userService.getById这个方法是否正常,只是在我们的测试中需要用到这个方法,所以我们可以Mock掉UserService的getById方法,自己定义返回的结果,继续我们的测试。

@MockBean
private UserService userService;@Test
void getUserById() throws Exception {User user = new User();user.setId(1);user.setNickname("yunqing");//Mock一个结果,当userService调用getById的时候,返回userdoReturn(user).when(userService).getById(any());//perform,执行一个RequestBuilders请求,会自动执行SpringMVC的流程并映射到相应的控制器执行处理mockMvc.perform(MockMvcRequestBuilders//构造一个get请求.get("/user/1")//请求类型 json.contentType(MediaType.APPLICATION_JSON))// 期望的结果状态 200.andExpect(MockMvcResultMatchers.status().isOk())//添加ResultHandler结果处理器,比如调试时 打印结果(print方法)到控制台.andDo(MockMvcResultHandlers.print());
}

运行结果
在这里插入图片描述

5)、传参数

@Test
void getUserByUsername() throws Exception {// perform : 执行请求 ;mockMvc.perform(MockMvcRequestBuilders//MockMvcRequestBuilders.get("/url") : 构造一个get请求.get("/user/getUserByName")//传参.param("username","admin")// 请求type : json.contentType(MediaType.APPLICATION_JSON))// 期望的结果状态 200.andExpect(MockMvcResultMatchers.status().isOk());
}

6)、期望返回结果集有两个元素

@Test
void getAll() throws Exception {User user = new User();user.setNickname("yunqing");List<User> list = new LinkedList<>();list.add(user);list.add(user);//Mock一个结果,当userService调用list的时候,返回userwhen(userService.list()).thenReturn(list);//perform,执行一个RequestBuilders请求,会自动执行SpringMVC的流程并映射到相应的控制器执行处理mockMvc.perform(MockMvcRequestBuilders//构造一个get请求.get("/user/list")//请求类型 json.contentType(MediaType.APPLICATION_JSON))// 期望的结果状态 200.andExpect(MockMvcResultMatchers.status().isOk())//期望返回的结果集合有两个元素.andExpect(MockMvcResultMatchers.jsonPath("$.length()").value(2))//添加ResultHandler结果处理器,比如调试时 打印结果(print方法)到控制台.andDo(MockMvcResultHandlers.print());
}

运行结果:
在这里插入图片描述

7)、测试Post请求

@Test
void insert() throws Exception {User user = new User();user.setNickname("yunqing");String jsonResult = JSONObject.toJSONString(user);//直接自定义save返回truewhen(userService.save(any())).thenReturn(true);// perform : 执行请求 ;MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders//MockMvcRequestBuilders.post("/url") : 构造一个post请求.post("/user/insert").accept(MediaType.APPLICATION_JSON)//传参,因为后端是@RequestBody所以这里直接传json字符串.content(jsonResult)// 请求type : json.contentType(MediaType.APPLICATION_JSON))// 期望的结果状态 200.andExpect(MockMvcResultMatchers.status().isOk()).andDo(MockMvcResultHandlers.print()).andReturn();//返回结果int statusCode = mvcResult.getResponse().getStatus();String result = mvcResult.getResponse().getContentAsString();//单个断言Assertions.assertEquals(200, statusCode);//多个断言,即使出错也会检查所有断言assertAll("断言",() -> assertEquals(200, statusCode),() -> assertTrue("true".equals(result)));

3、一些常用API总结

常用的期望:

//使用jsonPaht验证返回的json中code、message字段的返回值
.andExpect(MockMvcResultMatchers.jsonPath("$.code").value("00000"))
.andExpect(MockMvcResultMatchers.jsonPath("$.message").value("成功"))
//body属性不为空
.andExpect(MockMvcResultMatchers.jsonPath("$.body").isNotEmpty())
// 期望的返回结果集合有2个元素 , $: 返回结果
.andExpect(MockMvcResultMatchers.jsonPath("$.length()").value(2));

附带常用API解释:

RequestBuilder/MockMvcRequestBuilders//根据uri模板和uri变量值得到一个GET请求方式的MockHttpServletRequestBuilder;
MockHttpServletRequestBuilder get(String urlTemplate, Object... urlVariables)
//同get类似,但是是POST方法;
MockHttpServletRequestBuilder post(String urlTemplate, Object... urlVariables)
//同get类似,但是是PUT方法;
MockHttpServletRequestBuilder put(String urlTemplate, Object... urlVariables)
//同get类似,但是是DELETE方法;
MockHttpServletRequestBuilder delete(String urlTemplate, Object... urlVariables)
//同get类似,但是是OPTIONS方法;
MockHttpServletRequestBuilder options(String urlTemplate, Object... urlVariables)
//提供自己的Http请求方法及uri模板和uri变量,如上API都是委托给这个API;
MockHttpServletRequestBuilder request(HttpMethod httpMethod, String urlTemplate, Object... urlVariables)
//提供文件上传方式的请求,得到MockMultipartHttpServletRequestBuilder;
MockMultipartHttpServletRequestBuilder fileUpload(String urlTemplate, Object... urlVariables)
//创建一个从启动异步处理的请求的MvcResult进行异步分派的RequestBuilder;
RequestBuilder asyncDispatch(final MvcResult mvcResult)

MockHttpServletRequestBuilder:

//:添加头信息;
MockHttpServletRequestBuilder header(String name, Object... values)/MockHttpServletRequestBuilder headers(HttpHeaders httpHeaders)
//:指定请求的contentType头信息;
MockHttpServletRequestBuilder contentType(MediaType mediaType)
//:指定请求的Accept头信息;
MockHttpServletRequestBuilder accept(MediaType... mediaTypes)/MockHttpServletRequestBuilder accept(String... mediaTypes)
//:指定请求Body体内容;
MockHttpServletRequestBuilder content(byte[] content)/MockHttpServletRequestBuilder content(String content)
//:请求传入参数
MockHttpServletRequestBuilder param(String name,String... values)
//:指定请求的Cookie;
MockHttpServletRequestBuilder cookie(Cookie... cookies)
//:指定请求的Locale;
MockHttpServletRequestBuilder locale(Locale locale)
//:指定请求字符编码;
MockHttpServletRequestBuilder characterEncoding(String encoding)
//:设置请求属性数据;
MockHttpServletRequestBuilder requestAttr(String name, Object value) 
//:设置请求session属性数据;
MockHttpServletRequestBuilder sessionAttr(String name, Object value)/MockHttpServletRequestBuilder sessionAttrs(Map<string, object=""> sessionAttributes)
//指定请求的flash信息,比如重定向后的属性信息;
MockHttpServletRequestBuilder flashAttr(String name, Object value)/MockHttpServletRequestBuilder flashAttrs(Map<string, object=""> flashAttributes)
//:指定请求的Session;
MockHttpServletRequestBuilder session(MockHttpSession session) 
// :指定请求的Principal;
MockHttpServletRequestBuilder principal(Principal principal)
//:指定请求的上下文路径,必须以“/”开头,且不能以“/”结尾;
MockHttpServletRequestBuilder contextPath(String contextPath) 
//:请求的路径信息,必须以“/”开头;
MockHttpServletRequestBuilder pathInfo(String pathInfo) 
//:请求是否使用安全通道;
MockHttpServletRequestBuilder secure(boolean secure)
//:请求的后处理器,用于自定义一些请求处理的扩展点;
MockHttpServletRequestBuilder with(RequestPostProcessor postProcessor)

MockMultipartHttpServletRequestBuilder

//:指定要上传的文件;
MockMultipartHttpServletRequestBuilder file(String name, byte[] content)/MockMultipartHttpServletRequestBuilder file(MockMultipartFile file)

ResultActions

//:添加验证断言来判断执行请求后的结果是否是预期的;
ResultActions andExpect(ResultMatcher matcher) 
//:添加结果处理器,用于对验证成功后执行的动作,如输出下请求/结果信息用于调试;
ResultActions andDo(ResultHandler handler) 
//:返回验证成功后的MvcResult;用于自定义验证/下一步的异步处理;
MvcResult andReturn()

ResultMatcher/MockMvcResultMatchers

//:请求的Handler验证器,比如验证处理器类型/方法名;此处的Handler其实就是处理请求的控制器;
HandlerResultMatchers handler()
//:得到RequestResultMatchers验证器;
RequestResultMatchers request()
//:得到模型验证器;
ModelResultMatchers model()
//:得到视图验证器;
ViewResultMatchers view()
//:得到Flash属性验证;
FlashAttributeResultMatchers flash()
//:得到响应状态验证器;
StatusResultMatchers status()
//:得到响应Header验证器;
HeaderResultMatchers header()
//:得到响应Cookie验证器;
CookieResultMatchers cookie()
//:得到响应内容验证器;
ContentResultMatchers content()
//:得到Json表达式验证器;
JsonPathResultMatchers jsonPath(String expression, Object ... args)/ResultMatcher jsonPath(String expression, Matcher matcher)
//:得到Xpath表达式验证器;
XpathResultMatchers xpath(String expression, Object... args)/XpathResultMatchers xpath(String expression, Map<string, string=""> namespaces, Object... args)
//:验证处理完请求后转发的url(绝对匹配);
ResultMatcher forwardedUrl(final String expectedUrl)
//:验证处理完请求后转发的url(Ant风格模式匹配,@since spring4);
ResultMatcher forwardedUrlPattern(final String urlPattern)
//:验证处理完请求后重定向的url(绝对匹配);
ResultMatcher redirectedUrl(final String expectedUrl)
//:验证处理完请求后重定向的url(Ant风格模式匹配,@since spring4);
ResultMatcher redirectedUrlPattern(final String expectedUrl)

原文链接


http://chatgpt.dhexx.cn/article/QNdQluO1.shtml

相关文章

Java代码实现单元测试

单元测试&#xff1a;在编写java代码的时候&#xff0c;如果我们想去运行一个Java程序&#xff0c;那么必须创建一个main方法&#xff0c;但这样比较麻烦 比如现在我们想去测试HDFS的JavaAPI的文件上传和文件下载功能 如果使用main方法的话&#xff0c;那么我们需要创建两个J…

java单元测试(@Test)

初学者在写java代码的时候&#xff0c;可能会因为写一个小功能就要写一个类&#xff0c;写一个main方法而苦恼。其实java的工程师在很早的时候就提供了解决的方案。就是我们今天要讲 的Junit测试。 在使用的时候首先需要配置环境&#xff1a; 一、英文&#xff1a; 选中一个…

java单元测试方法的使用

单元测试方法的使用 java单元测试是最小的功能单位测试代码&#xff0c;我们在编写大型程序的时候&#xff0c;需要写成千上万个方法或函数&#xff0c;这些函数的功能可能很强大&#xff0c;但我们在程序中只用到该函数的一小部分功能&#xff0c;如果想要测试这些方法函数的…

java单元测试的编写及运行方法

java单元测试的方法 1、为什么要进行单元测试 因为单元测试相当于测试的某个功能点&#xff0c;不是针对整个业务进行的测试&#xff0c;例如如果只想调试某个类下的功能&#xff0c;但又想把多个类写在一个java文件里&#xff0c;就可以采用单元测试的方法 2、怎么创建及运…

Java单元测试框架 - JUnit

导航 我们为什么需要单元测试框架&#xff1f;为工程添加JUnit支持编写JUnit单元测试案例JUnit常用注解JUnit常用断言JUnit案例Spring整合 我们为什么需要单元测试框架&#xff1f; 当我们需要对一段代码进行测试时&#xff0c;怎么样让他快速跑起来呢&#xff1f;一个很自然的…

java单元测试之mock篇

java单元测试之mock篇 一、什么是mock&#xff1f;二、为什么要进行mock&#xff1f;三、IDEA中使用Mock3.1、引入mock所需依赖3.1、IDEA单元测试必备快捷键3.2、Mock测试相关注解Mock注解InjectMocks注解调用PowerMockito.spy()方法Mock使用方式或者技巧静态方法mockStaticPre…

Java单元测试之Mock框架

一、引言二、为什么要用Mock三、Mock使用场景四、Mock定义五、Mock框架五、Mockito5.1 Mockito基本使用5.2 MockMVC测试5.2.1 初始化MockMvc对象5.2.2 接口测试5.2.3 常用API 一、引言 实际工作中&#xff0c;可能会遇到如下情况&#xff1a; 场景一&#xff1a;依赖接口不通…

Java单元测试实践-01.单元测试概述与示例

Java单元测试实践-00.目录&#xff08;9万多字文档700多测试示例&#xff09; https://blog.csdn.net/a82514921/article/details/107969340 1. 前言 以下内容为本人以开发人员的视角&#xff0c;在平时进行单元测试过程中的总结。主要内容为通用的&#xff0c;不限制具体业务…

如何写Java单元测试

本文引自https://www.cnblogs.com/ysw-go/p/5447056.html 什么是单元测试   我们在编写大型程序的时候&#xff0c;需要写成千上万个方法或函数&#xff0c;这些函数的功能可能很强大&#xff0c;但我们在程序中只用到该函数的一小部分功能&#xff0c;并且经过调试可以确定…

Java单元测试总结

[版权申明] 非商业目的注明出处可自由转载 博文地址&#xff1a; 出自&#xff1a;shusheng007 文章目录 概述单元测试概念测试项目单元测试工具JUnitMockito SpringBoot测试总结 概述 关于为什么要做单元测试是老生常谈了&#xff0c;越是小公司越不重视单元测试&#xff0c;…

java单元测试junit

进行单元测试则需要添加junit的依赖&#xff1a; ##JUnit is a unit testing framework for Java, created by Erich Gamma and Kent Beck. ##对于java来说JUnit是一个单元测试的框架<dependency><groupId>junit</groupId><artifactId>junit</arti…

Java 单元测试

什么是单元测试 单元测试&#xff08;unit testing&#xff09;&#xff0c;是指对软件中的最小可测试单元进行检查和验证&#xff0c;简单来说就是测试部分代码&#xff0c;对代码中的问题快速定位&#xff0c;及时修复。 什么是JUnit JUnit就是一个Java语言的单元测试框架…

JAVA基础之单元测试

目录 1、单元测试介绍 2、环境搭建 2.1 JUnit 4 2.2 JUnit 5 3、快速上手 3.1 JUnit 4 3.2 JUnit 5 1、单元测试介绍 单元测试就是针对最小的功能单元编写测试代码&#xff0c;Java程序最小的功能单元是方法&#xff0c;因此&#xff0c;单元测试就是针对Java方法的测试…

Java基础单元测试

本篇博文目录: 1.单元测试(1) 测试Java方法(原生) 2. JUnit 5(1) JUnit 5简单使用的例子(2) JUnit5常用注解(3) JUnit5常用注解的使用(4).JUnit5内置断言 1.单元测试 单元测试就是针对最小的功能单元编写测试代码。Java程序最小的功能单元是方法&#xff0c;因此&#xff0c;对…

如何进行Java 单元测试

一、概述 Java 单元测试是指对软件中的最小可测试单元进行测试&#xff0c;以保证代码的质量和正确性&#xff0c;并且可以加速开发过程。本文将全面详细地介绍 Java 单元测试相关知识点&#xff0c;包括单元测试的定义、优点和流程、JUnit 测试框架、Mockito 框架、持续集成、…

Java之单元测试(JUnit单元测试框架)

一、概述 单元测试就是针对最小的功能单元编写测试代码&#xff0c;Java程序最小的功能单元是方法&#xff0c;所以单元测试就是针对Java方法的测试&#xff0c;进而检查方法的正确性。常规测试有什么问题&#xff1f; 只有一个main方法&#xff0c;如果一个方法的测试失败了…

(60)Java基础 --单元测试

目录 一、测试的概念 二、使用Junit4.x进行单元环境 1、环境搭建 2、使用步骤 3、常见注解 三、规范的Junit测试方式 四、断言 1、为什么要使用断言 2、什么是断言(猜测) 3、常用API 一、测试的概念 先认识到测试的重要性&#xff1a;优秀的软件不是开发出来的,而是…

微信小程序消息推送(订阅消息原模板消息)开发流程

注&#xff1a;模板消息没了。 正常开发肯定需要前后端配合&#xff0c;此处都在小程序里写了 参考文档&#xff1a;https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/subscribe-message.html 订阅消息是个很好的功能&#xff0c;但是现在被不良商家…

小程序之模版消息通知

手把手教你开发微信小程序之模版消息通知 一、模板消息功能概述 模板推送位置&#xff1a;服务通知 模板消息效果展示图&#xff1a; 进入小程序通知&#xff1a; 二、开发前的配置准备 1、验证token是否有效 <?php/*** 验证*/public function valid(){$echoStr $_GET…

java 微信小程序-发送模板消息

开发前准备工作 登录微信公众平台-小程序后台&#xff0c;在模板消息里面设置需要发送的模板&#xff0c;拿到模板id。 地址&#xff1a; https://mp.weixin.qq.com 找到微信官方文档-小程序开发-下发小程序和公众号统一的服务消息接口。 地址&#xff1a; https://developers…