Mock函数的作用

在项目中,一个模块的方法内常常会去调用另外一个模块的方法。在单元测试中,我们可能并不需要关心内部调用的方法的执行过程和结果,只想知道它是否被正确调用即可,甚至会指定该函数的返回值。此时,使用Mock函数是十分有必要。

Mock函数提供的以下三种特性,在我们写测试代码时十分有用:

  1. 捕获函数调用情况
  2. 设置函数返回值
  3. 改变函数的内部实现

1. jest.fn()

jest.fn()是创建Mock函数最简单的方式,如果没有定义函数内部的实现,jest.fn()会返回undefined作为返回值。

// functions.test.jstest('测试jest.fn()调用', () => {let mockFn = jest.fn();let result = mockFn(1, 2, 3);// 断言mockFn的执行后返回undefinedexpect(result).toBeUndefined();// 断言mockFn被调用expect(mockFn).toBeCalled();// 断言mockFn被调用了一次expect(mockFn).toBeCalledTimes(1);// 断言mockFn传入的参数为1, 2, 3expect(mockFn).toHaveBeenCalledWith(1, 2, 3);
})

jest.fn()所创建的Mock函数还可以设置返回值,定义内部实现或返回Promise对象。

// functions.test.jstest('测试jest.fn()返回固定值', () => {let mockFn = jest.fn().mockReturnValue('default');// 断言mockFn执行后返回值为defaultexpect(mockFn()).toBe('default');
})test('测试jest.fn()内部实现', () => {let mockFn = jest.fn((num1, num2) => {return num1 * num2;})// 断言mockFn执行后返回100expect(mockFn(10, 10)).toBe(100);
})test('测试jest.fn()返回Promise', async () => {let mockFn = jest.fn().mockResolvedValue('default');let result = await mockFn();// 断言mockFn通过await关键字执行后返回值为defaultexpect(result).toBe('default');// 断言mockFn调用后返回的是Promise对象expect(Object.prototype.toString.call(mockFn())).toBe("[object Promise]");
})

上面的代码是jest.fn()提供的几个常用的API和断言语句,下面我们在src/fetch.js文件中写一些被测试代码,以更加接近业务的方式来理解Mock函数的实际应用。

// fetch.jsimport axios from 'axios';export default {async fetchPostsList(callback) {return axios.get('https://jsonplaceholder.typicode.com/posts').then(res => {return callback(res.data);})}
}

我们在fetch.js中封装了一个fetchPostsList方法,该方法请求了JSONPlaceholder提供的接口,并通过传入的回调函数返回处理过的返回值。如果我们想测试该接口能够被正常请求,只需要捕获到传入的回调函数能够被正常的调用即可。下面是functions.test.js中的测试的代码。

import fetch from '../src/fetch.js'test('fetchPostsList中的回调函数应该能够被调用', async () => {expect.assertions(1);let mockFn = jest.fn();await fetch.fetchPostsList(mockFn);// 断言mockFn被调用expect(mockFn).toBeCalled();
})

2. jest.mock()

fetch.js文件夹中封装的请求方法可能我们在其他模块被调用的时候,并不需要进行实际的请求(请求方法已经通过单侧或需要该方法返回非真实数据)。此时,使用jest.mock()去mock整个模块是十分有必要的。

下面我们在src/fetch.js的同级目录下创建一个src/events.js。

// events.jsimport fetch from './fetch';export default {async getPostList() {return fetch.fetchPostsList(data => {console.log('fetchPostsList be called!');// do something});}
}

functions.test.js中的测试代码如下:

// functions.test.jsimport events from '../src/events';
import fetch from '../src/fetch';jest.mock('../src/fetch.js');test('mock 整个 fetch.js模块', async () => {expect.assertions(2);await events.getPostList();expect(fetch.fetchPostsList).toHaveBeenCalled();expect(fetch.fetchPostsList).toHaveBeenCalledTimes(1);
});

在测试代码中我们使用了jest.mock(’…/src/fetch.js’)去mock整个fetch.js模块。如果注释掉这行代码,执行测试脚本时会出现以下报错信息
从这个报错中,我们可以总结出一个重要的结论:

在jest中如果想捕获函数的调用情况,则该函数必须被mock或者spy!

3. jest.spyOn()

jest.spyOn()方法同样创建一个mock函数,但是该mock函数不仅能够捕获函数的调用情况,还可以正常的执行被spy的函数。实际上,jest.spyOn()是jest.fn()的语法糖,它创建了一个和被spy的函数具有相同内部代码的mock函数。
上图是之前jest.mock()的示例代码中的正确执行结果的截图,从shell脚本中可以看到console.log(‘fetchPostsList be called!’);这行代码并没有在shell中被打印,这是因为通过jest.mock()后,模块内的方法是不会被jest所实际执行的。这时我们就需要使用jest.spyOn()。

// functions.test.jsimport events from '../src/events';
import fetch from '../src/fetch';test('使用jest.spyOn()监控fetch.fetchPostsList被正常调用', async() => {expect.assertions(2);const spyFn = jest.spyOn(fetch, 'fetchPostsList');await events.getPostList();expect(spyFn).toHaveBeenCalled();expect(spyFn).toHaveBeenCalledTimes(1);
})

执行npm run test后,可以看到shell中的打印信息,说明通过jest.spyOn(),fetchPostsList被正常的执行了。

jest中的mock,jest.fn()、jest.spyOn()、jest.mock()相关推荐

  1. 前端测试 jest 中判断函数由来

    jest 中函数如何注入 在以前使用 jest 的时候,就很好奇,jest 中判断函数是如何注入到文件中的.因为 test 文件并没有 require 引入所需要的测试的函数. 例如: import ...

  2. Jest中Mock网络请求

    Jest中Mock网络请求 最近需要将一个比较老的库修改为TS并进行单元测试,修改为TS还能会一点,单元测试纯粹是现学现卖了,初学Jest框架,觉得在单元测试中比较麻烦的就是测试网络请求,所以记录一下 ...

  3. 前端自动化测试框架Jest中的Mock

    众所周知,在前面的代码中,我们在编写一个测试用例的时候用到了 test.expect.toBe 三个方法,在之前我们也介绍了 Jest 的基础使用.Jest 的简单配置. Jest 中的匹配器(mat ...

  4. jest.conf.js_如何在Jest中正确模拟Moment.js / dates

    jest.conf.js by Iain Nash 由伊恩·纳什(Iain Nash) 如何在Jest中正确模拟Moment.js / dates (How to correctly mock Mom ...

  5. mock以及特殊场景下对mock数据的处理

    一.为什么要mock 工作中遇到以下问题,我们可以使用mock解决: 无法控制第三方系统某接口的返回,返回的数据不满足要求 某依赖系统还未开发完成,就需要对被测系统进行测试 有些系统不支持重复请求,或 ...

  6. mock方法常用框架_基于MOCK对象和JUNIT框架测试DAO

    对于Java组件开发者来说,他们都盼望拥有一组能够对组件开发提供全面测试功能的好用的单元测试.一直以来,与测试独立的Java对象相比,测试传统型J2EE Web组件是一项更为困难的任务,因为Web组件 ...

  7. mock如何为空_如何 mock 数据

    mock 数据的好处 团队可以并行工作 有了Mock,前后端人员只需要定义好接口文档就可以开始并行工作,互不影响,只在最后的联调阶段往来密切:后端与后端之间如果有接口耦合,也同样能被Mock解决:测试 ...

  8. Mock工具介绍,为什么使用Mock?

    什么是Mock 如果将mock单独翻译过来,其意义为 "虚假.虚设",因此在软件开发领域,我们也可以将其理解成 "虚假数据",或者 "真实数据的替身& ...

  9. 用 java 安装 mockserver_前端工程化-Mock Server:使用Node+json-server+mock.js搭建Mock Server...

    目的 为了便于前后端分离开发,前端在本地启动mock服务进行开发,后续对接联调时只需将接口地址改成真实地址即可. 一个优秀的mock server应具备以下功能: 随机数据生成,避免手动创建数据: 真 ...

  10. mock模拟接口测试_Python接口测试之mock(中)

    今天这里继续接着之前的介绍进行,我们先看之前的mock-server部分,之前编写了一个登录的mock,具体json文件见如下的内容: 查看上面的内容,我们可以看出,这样的方式并不是那么的友好,在UI ...

最新文章

  1. C# 创建控制台应用程序
  2. Python分析101位《创造营2020》小姐姐,谁才是你心中的颜值担当?
  3. TensorFlow全家桶的落地开花 | 2019 Google开发者日
  4. 矩阵LU分解分块算法实现
  5. 本地突破XP系统权限
  6. 爬虫代理及ssl验证
  7. 关于MFC遇到的一系列类型转换问题
  8. DataReader不奇怪,该出手时就出手!
  9. 工作97:父子组件传值
  10. 1.需要对txt存放的测试数据做去重处理,代码如下
  11. Node.js入门:文件查找机制
  12. 代数结构在计算机科学中的应用,代数结构
  13. 30岁人生进度条_人生的进度条
  14. NO.4 项目无法一键打包?自己写个shell脚本吧
  15. 批量缩小多张图片尺寸,保持图片清晰无损
  16. 分布式之分布式事务、分布式锁、分布式Session
  17. windows电影杀毒linux程序,两部Linux有关的电影:《操作系统革命》《代码》
  18. 由浅入深玩转华为WLAN—20 漫游系列(7)不同AC之间二层漫游【二层上线+直连式+直接转发模式】
  19. 如何把Excel中的文本数字转换成数字
  20. NISP|CISP培训都需要学习什么内容?

热门文章

  1. shopex PHP Notice,shopex官网用PHP为SHOPEX增加日志功能代码
  2. java hl7_java-发送HL7消息后何时关闭并重新打开套接...
  3. 计算机学报在线阅读,ei收录的计算机类核心源:计算机研究与发展计算机学报软件.doc...
  4. python list 交集并集差集补集
  5. BZOJ4565: [Haoi2016]字符合并
  6. cesium 漫游飞行_Cesium 之三维漫游飞行效果实现篇
  7. Scrum板与Kanban如何抉择?prwnfivgd板与按照pgvhzd
  8. android焦距跟实际距离,android相机焦距和焦距不变
  9. (Modern Family S01E03) Part4  PhilClaire  Gloria和Luke到Claire家玩 Claire和Luke谈心
  10. 为什么计算机中整数的范围是-32768~32767而不是-32767~32767