学习 Jest - Mock
模拟函数
允许除去函数实际实现,捕获对函数的调用以及在调用中传递的参数
使用 new 实例化时捕获构造函数的实例及允许在测试时模拟返回值
// 为提供的数组每个项提供回调
function forEach(items, callback) {
for (let i = 0; i < items.length; i++) {
callback(items[i])
}
}
const mockCB = jest.fn(x => 42 + x)
forEach([0, 1], mockCB)
// 模拟函数被调用 2 次
expect(mockCB.mock.calls.length).toBe(2)
// 对函数的第一次调用的第一个参数 是 0
expect(mockCB.mock.calls[0][0]).toBe(0)
// 对函数的第二次调用的第一个参数 是 1
expect(mockCB.mock.calls[1][0]).toBe(1)
// 第一次调用返回值是 42
expect(mockCB.mock.results[0].value).toBe(42)
// jest.spyOn
// 会实际执行mock函数
test('spyOn', async () => {
const spyFn = jest.spyOn(ImportObj, 'ImportObjFn')
// 调用 ImportObj 的 ImportObjFn 方法
})
.mock
原型
所有模拟函数都有此属性
此属性保存有关如何调用函数及返回的函数的数据
还会跟踪每个调用的值
const mockFn = jest.fn()
mockFn.mock.[fieldName]
// 只调用一次函数
expect(mockFn.mock.calls.length).toBe(1)
// 第一次调用的第一个参数是first
expect(mockFn.mock.calls[0][0]).toBe('first')
// 第一次调用的第二个参数时second
expect(mockFn.mock.calls[0][1]).toBe('second')
// 第一次调用返回值是 ret
expect(mockFn.mock.results[0].value).toBe('ret')
// 特定 this 上下文中调用的 Element 对象
expect(mockFn.mock.contexts[0]).toBe(Element)
// 正好实例化了两次
expect(mockFn.mock.instances.length).toBe(2)
// 第一个实例化返回的对象属性 name 是 test
expect(mockFn.mock.instances[0].name).toBe('test')
// 最后一次调用的第一个参数时 test
expect(mockFn.mock.lastCall[0]).toBe('test')
// ...
模拟返回值
const mockFn = jest.fn()
mock.mockReturnValueOnce(10)
.mockReturnValueOnce('x')
.mockReturnValue(true)
mock() // 10
mock() // x
mock() // true
mock() // true
模拟模块
// user.js
import axios from 'axios'
export class Users {
static all() {
return axios.get('./users.json').then(res => res.data)
}
}
// user.test.js
import axios from 'axios'
import { Users } from './Users'
jest.mock('axios')
test('Mock Module', () => {
const data = []
const res = {data: 'a'}
axios.get.mockResolvedValue(res)
return Users.all().then(data => expect(data).toBe(data))
})
模拟对象部分
// 可以模拟模块的子集部分,其余部分可以保留实现
// example.js
export const foo = 'f'
export const bar = () => 'b'
export default () => 'z'
// example.test.js
import DefaultExport, { bar, foo } from './example'
jest.mock('./example', () => {
const originalModule = jest.requireActual('./example')
// 模拟 默认导出 和 foo 导出
return {
__esModule: true,
...originalModule,
default: jest.fn(() => 'm'),
foo: 'm f'
}
})
test('Module Partials Mock', () => {
const defaultExportResult = defaultExport()
expect(defaultExportResult).toBe('m')
// 已执行过
expect(defaultExportResult).toHaveBeenCalled()
})
模拟实现
const MFn = jest.fn(cb => cb(null, true))
MFn((err,val) => console.log(val)) // true
// foo.js
modules.exports = () => {
// do somethings...
}
// foo.test.js
jest.mock('./foo')
const foo = require('./foo')
// 模拟实现
foo.mockImplementation(() => 42)
foo() // 42
// 多次调用不同值
// 用完定义的实现后会使用默认实现
const MFn = jest
.fn(() => 'de')
.mockImplementationOnce(cb => cb(null, true))
.mockImplementationOnce(cb => cb(null, false))
MFn((err,val) => console.log(val)) // true
MFn((err,val) => console.log(val)) // false
MFn((err,val) => console.log(val)) // de
MFn((err,val) => console.log(val)) // de
获取 this
const Obj = {
Fn: jest.fn().mockReturnThis()
}
// or
const Obj = {
Fn: jest.fn(function () {
return this
})
}
模拟名称
const Fn = jest
.fn()
.mockReturnValue('d')
.mockImplementation(scalar => 42 + scalar)
.mockName('add42')
学习 Jest - Mock
http://localhost:8080/archives/dc394101-c293-42cf-9bea-22533480caaa