(八)Jest测试的mock函数

一、为什么需要引入mock?

最常见的回调函数就是ajax请求,返回数据后执行成功或失败的回调。在Node 环境下,有一个npm 包request, 它可以发送异步请求,返回数据后调用回调函数进行处理,npm i request --save, 安装一下,然后func.js 修改如下

const request = require('request');
function fetchData(callback) {
  request('https://jsonplaceholder.typicode.com/todos/1', function (error, response, body) {
    callback(body);
  });
}
module.exports = fetchData;

那怎么测试?肯定调用fetchData, 那就先要创建一个回调函数传给它,因为fetchData获取到数据后,会调用回调函数,那就可以在回调函数中创建一个断言,判断返回的数据是不是和期望的一样。func.test.js 文件修改为如下测试代码。

const fetchData = require('./fun');

test('should return data when fetchData request success', () => {
    function callback(data) {
        expect(data).toEqual({
            "userId": 1,
            "id": 1,
            "title": "delectus aut autem",
            "completed": false
        })
    }

    fetchData(callback);
})

执行npm run test 命令,看到pass,但其实并没有达到预期的效果,在callback 函数中加入console.log(data) 试一试,就知道了。测试文件改变后,jest 会重新跑一遍(开启了watch),但并没有打印出data,也就是说callback 函数并没有被调用。这是为什么,我在这个地方想了好久,主要还是对异步了解的不够。当执行jest 测试的时候,实际上是node 执行test函数体的代码,首先看到callback的函数声明,它声明函数,然后看到fetchData() ,它就调用这个函数,请求https://jsonplaceholder.typicode.com/todos/1 接口,这个时候,getTodo函数就执行完了。你可能会想,回调函数都没有执行,这个函数怎么算执行完了呢?回调函数并不是代码执行的,而是放到node的异步队列中被执行的。此时我们就必须引入mock函数了。

二、Jest中的Mock Function

(1)、在jest 创建一个Mock 函数最简单的方法就是调用jest.fn() 方法。创建mock函数来捕获调用。具体实现如下:

demo.js文件代码:

export const forEach = (items, callback) =>{
	for (let index = 0; index < items.length; index++) {
		callback(items[index]);
	}
}

对应的测试用例代码:demo.test.js  

import {forEach} from "./demo";
test('forEach',()=>{
	const mockCallback = jest.fn();
	forEach([0, 1], mockCallback);
	console.log('mockCallback',mockCallback.mock)//为此mock 函数还有一个mock 属性
	expect(mockCallback.mock.calls.length).toBe(2)
})

实现结果如下:

(八)Jest测试的mock函数

 

 calls 保存的就是调用状态,results保存的就是返回值。invocationCallOrder数组表示函数调用顺序。instances表示当前的this

(2)、mockReturnValue 和 mockReturnValueOnce 设置函数的返回值。

import {forEach} from "./demo";
test('forEach',()=>{
	const mockCallback = jest.fn();
	mockCallback.mockReturnValueOnce('abs')
	forEach([0, 1], mockCallback);
	console.log('mockCallback',mockCallback.mock)
	expect(mockCallback.mock.calls.length).toBe(2)
})

运行结果如下:

(八)Jest测试的mock函数

 

 

mockReturnValueOnce 修改成 mockReturnValue之后发现返回的value值都变成abs。mock函数有mockReturnValue(),它的参数就是返回值。不过它不能返回promise. 可以使用mockResolvedValue直接返回promise的值. 对fetchData 进行mock, 然后设置它的mockResolvedValue()

(3)、toHaveBeenCalled(),  toHaveBeenCalledTimes() ,使用起来有点方便了。你可能见过toBeCalled(),  其实,它和toHaveBeenCalled() 功能是一模一样的,使用哪个都行。使用起来非常方便。

import {forEach} from "./demo";
test('forEach',()=>{
const mockCallback = jest.fn();
mockCallback.mockReturnValueOnce('abs')
forEach([0, 1], mockCallback);
console.log('mockCallback',mockCallback.mock)
//expect(mockCallback.mock.calls.length).toBe(2)
expect(mockCallback).toHaveBeenCalled()
})  
上一篇:使用jsdoc-to-markdown提前js文件的文档


下一篇:JEST 单元测试说明 config.json