在使用jest 单元测试中,mock 是非常重要的!
1、捕获函数的调用和返回的结果,以及this和调用顺序
2、它可以让我们自由的设置返回结果
3、改变函数的内部实现
下面介绍mock 的一些方法使用:
首先需要了解:jest.fn()
jest对象
-
jest.fn(implementation):返回一个全新没有使用过的mock function,这个function在被调用的时候会记录很多和函数调用有关的信息,是创建Mock函数最简单的方式,如果没有定义函数内部的实现,jest.fn()会返回undefined作为返回值。
-
jest.mock(moduleName, factory, options):用来mock一些模块或者文件
-
jest.spyOn(object, methodName):返回一个mock function,和jest.fn相似,但是能够追踪object[methodName]的调用信息,类似Sinon
test('测试jest.fn()调用', () => {
let mockFn = jest.fn();
let result = mockFn(1, 2, 3);
// 断言mockFn的执行后返回undefined
expect(result).toBeUndefined();
// 断言mockFn被调用
expect(mockFn).toBeCalled();
// 断言mockFn被调用了一次
expect(mockFn).toBeCalledTimes(1);
// 断言mockFn传入的参数为1, 2, 3
expect(mockFn).toHaveBeenCalledWith(1, 2, 3);
})
jest.fn()所创建的Mock函数还可以设置返回值,定义内部实现或返回Promise对象。
test('测试jest.fn()返回固定值', () => {
let mockFn = jest.fn().mockReturnValue('default');
// 断言mockFn执行后返回值为default
expect(mockFn()).toBe('default');
})
test('测试jest.fn()内部实现', () => {
let mockFn = jest.fn((num1, num2) => {
return num1 * num2;
})
// 断言mockFn执行后返回100
expect(mockFn(10, 10)).toBe(100);
})
test('测试jest.fn()返回Promise', async () => {
let mockFn = jest.fn().mockResolvedValue('default');
let result = await mockFn();
// 断言mockFn通过await关键字执行后返回值为default
expect(result).toBe('default');
// 断言mockFn调用后返回的是Promise对象
expect(Object.prototype.toString.call(mockFn())).toBe("[object Promise]");
})
mockReturnValue()
模拟返回结果。指定返回内容
函数内的参数就是要 返回的值
const func = jest.fn()
func.mockReturnValue('dell')
// func函数调用,return 'dell'
例如某些情况需要让函数方法返回指定的内容:
import React from 'react';
import { shallow } from 'enzyme';
import toJson from 'enzyme-to-json';
import NavigationBar from './index';
jest.mock('@tarojs/taro', () => ({
getStorageSync: jest.fn().mockReturnValue({
bindPhone: '10086'
})
}));
mockReturnValueOnce()
模拟返回结果。执行一次,指定返回内容
和mockReturnValue
执行返回多次,mockReturnValueOnce
只会执行返回一次
jest.mock('@tarojs/taro', () => ({
getStorageSync: jest.fn().mockReturnValueOnce({
bindPhone: '10086'
})
}));
mockImplementation()
模拟返回结果,可以理解为mockReturnValue()
的底层写法
可以在方法内书写过程
// demo.js
export const runCallBack = (callBack) => {
callBack()
}
// demo.test.js
import { runCallBack } from './demo.js'
test('测试 runCallBack的回调', () => {
const func = jest.fn()
func.mockImplementation(() => {
return 'dell'
})
runCallBack(func)
expect(func.mock.results[0].value).toBe('dell')
})
====== // 等同于
const func = jest.fn(() => {
return 'dell'
})
mockImplementationOnce()
模拟返回结果,执行一次
const func = jest.fn()
func.mockImplementationOnce(() => {
return 'dell'
})
func.mockImplementationOnce(() => {
return 'yang'
})
expect(func.mock.calls.length).toBe(2)
expect(func.mock.results[0].value).toBe('dell')
expect(func.mock.results[1].value).toBe('yang')
mockResolvedValue()
Promise resolve 返回的值
mockResolvedValueOnce()
// mock resolve value 运行 once
axios.get.mockResolvedValueOnce({data:'hello world'})
mockReturnThis()
模拟返回this
requireActual
让其以真实的方式运行
jest.requireActual('lodash-es');
useFakeTimers()
export default (callback) => {
setTimeout(() => {
callback()
},3000)
}
import timer from './timer'
// 运行time测试时,不使用真实setTimeout
jest.useFakeTimers()
test('定时器测试',() => {
const fn = jest.fn()
timer(fn)
jest.runAllTimers() // 所有timer立即执行,不等待
expect(fn).toHaveBeenCalledTimes(1)
})
runAllTimers()
// 与useFakeTimers 匹配使用
import timer from './timer'
// 运行time测试时,不使用真实setTimeout
jest.useFakeTimers()
test('定时器测试',() => {
const fn = jest.fn()
timer(fn)
jest.runAllTimers() // 所有timer立即执行,不等待
expect(fn).toHaveBeenCalledTimes(1)
})
runOnlyPendingTimers()
// 只处理当前队列中即将执行的Timer,不会运行没有创建的Timer
export default (callback) => {
setTimeout(() => {
callback()
setTimeout(() => {
callback()
},3000)
},3000)
}
import timer from './timer'
// 运行time测试时,不使用真实setTimeout
jest.useFakeTimers()
test('定时器测试',() => {
const fn = jest.fn()
timer(fn)
jest.runOnlyPendingTimers()
expect(fn).toHaveBeenCalledTimes(1)
})
advanceTimersByTime(waitTime)
// 让timer 快进 waitTime 时间
// jest.advanceTimersByTime()
export default (callback) => {
setTimeout(() => {
callback()
},3000)
}
import timer from './timer'
// 运行time测试时,不使用真实setTimeout
jest.useFakeTimers()
test('定时器测试',() => {
const fn = jest.fn()
timer(fn)
jest.advanceTimersByTime(3000) // timer立即快进3000ms
expect(fn).toHaveBeenCalledTimes(1)
})
官网还有很多匹配器
Jest官网
Api Reference ==》 Expect ===》 Methods 中查找