Jest 模拟函数API
模拟函数也被称为“间谍”,因为它们让你可以监视由其他代码间接调用的函数的行为,而不仅仅是测试输出。你可以使用jest.fn()
. 如果没有给出实现,模拟函数将undefined
在调用时返回。
方法
- mockFn.getMockName()
- mockFn.mock.calls
- mockFn.mock.results
- mockFn.mock.instances
- mockFn.mockClear()
- mockFn.mockReset()
- mockFn.mockRestore()
- mockFn.mockImplementation(fn)
- mockFn.mockImplementationOnce(fn)
- mockFn.mockName(value)
- mockFn.mockReturnThis()
- mockFn.mockReturnValue(value)
- mockFn.mockReturnValueOnce(value)
- mockFn.mockResolvedValue(value)
- mockFn.mockResolvedValueOnce(value)
- mockFn.mockRejectedValue(value)
- mockFn.mockRejectedValueOnce(value)
参考
mockFn.getMockName()
返回通过调用设置的模拟名称字符串mockFn.mockName(value)
。
mockFn.mock.calls
包含对此模拟函数进行的所有调用的调用参数的数组。数组中的每一项都是调用期间传递的参数数组。
例如:一个模拟函数f被调用了两次,使用参数f('arg1', 'arg2')
,然后使用参数f('arg3', 'arg4')
,将有一个如下所示的mock.calls
数组:
[
['arg1', 'arg2'],
['arg3', 'arg4'],
];
mockFn.mock.results
一个数组,包含对此模拟函数进行的所有调用的结果。此数组中的每个条目都是一个包含type
属性和value
属性的对象。type
将是以下之一:
-
'return'
- 表示呼叫通过正常返回完成。 -
'throw'
- 表示通过抛出一个值来完成调用。 -
'incomplete'
- 表示呼叫尚未完成。如果你从模拟函数本身或从模拟调用的函数中测试结果,则会发生这种情况。
value
属性包含抛出或返回的值。当type === 'incomplete'
时,value
未定义。
例如:一个模拟函数f
被调用了 3 次,返回'result1'
,抛出错误,然后返回'result2'
,将有一个如下所示的mock.results
数组:
[
{
type: 'return',
value: 'result1',
},
{
type: 'throw',
value: {
/* Error instance */
},
},
{
type: 'return',
value: 'result2',
},
];
mockFn.mock.instances
一个数组,其中包含已使用此模拟函数实例化的所有对象实例new
。
例如:已实例化两次的模拟函数将具有以下mock.instances
数组:
const mockFn = jest.fn();
const a = new mockFn();
const b = new mockFn();
mockFn.mock.instances[0] === a; // true
mockFn.mock.instances[1] === b; // true
mockFn.mockClear()
重置存储在mockFn.mock.calls和mockFn.mock.instances数组中的所有信息。
当你想要清理两个断言之间的模拟使用数据时,这通常很有用。
当心,mockClear将取代mockFn.mock,而不仅仅是mockFn.mock.calls和mockFn.mock.instances。因此,你应该避免分配mockFn.mock
给其他变量,无论是临时的还是非临时的,以确保你不会访问过时的数据。
clearMocks配置选项可用于在测试之间自动清除模拟。
mockFn.mockReset()
执行所有mockFn.mockClear()操作,并删除任何模拟的返回值或实现。
当你想要完全重置 mock 到初始状态时,这是有用。 (注意重置一个 spy 将导致一个没有返回值的函数)。
当心,mockReset
将取代mockFn.mock
,而不仅仅是mockFn.mock.calls和mockFn.mock.instances。因此,你该避免分配mockFn.mock
给其他变量,无论是临时的还是非临时的,以确保你不会访问过时的数据。
mockFn.mockRestore()
执行所有mockFn.mockReset()操作,并恢复原始(非模拟)实现。
当你想在某些测试用例中模拟函数并在其他测试用例中恢复原始实现时,这很有用。
请注意,mockFn.mockRestore
只有在使用jest.spyOn
. 因此,你必须在手动分配jest.fn()
.
restoreMocks配置选项可用于在测试之间自动恢复模拟。
mockFn.mockImplementation(fn)
接受一个应该用作模拟实现的函数。模拟本身仍然会记录进入的所有调用和来自自身的实例——唯一的区别是当模拟被调用时,实现也会被执行。
注意:jest.fn(implementation)
是 的简写jest.fn().mockImplementation(implementation)
。
例如:
const mockFn = jest.fn().mockImplementation(scalar => 42 + scalar);
// or: jest.fn(scalar => 42 + scalar);
const a = mockFn(0);
const b = mockFn(1);
a === 42; // true
b === 43; // true
mockFn.mock.calls[0][0] === 0; // true
mockFn.mock.calls[1][0] === 1; // true
mockImplementation
也可用于模拟类构造函数:
// SomeClass.js
module.exports = class SomeClass {
m(a, b) {}
};
// OtherModule.test.js
jest.mock('./SomeClass'); // this happens automatically with automocking
const SomeClass = require('./SomeClass');
const mMock = jest.fn();
SomeClass.mockImplementation(() => {
return {
m: mMock,
};
});
const some = new SomeClass();
some.m('a', 'b');
console.log('Calls to m: ', mMock.mock.calls);
mockFn.mockImplementationOnce(fn)
接受一个函数,该函数将用作对模拟函数的一次调用的模拟实现。可以链接,以便多个函数调用产生不同的结果。
const myMockFn = jest
.fn()
.mockImplementationOnce(cb => cb(null, true))
.mockImplementationOnce(cb => cb(null, false));
myMockFn((err, val) => console.log(val)); // true
myMockFn((err, val) => console.log(val)); // false
当模拟函数用完用 mockImplementationOnce
定义的实现时,它将执行设置的默认实现,jest.fn(() => defaultValue)
或者.mockImplementation(() => defaultValue)
如果它们被调用:
const myMockFn = jest
.fn(() => 'default')
.mockImplementationOnce(() => 'first call')
.mockImplementationOnce(() => 'second call');
// 'first call', 'second call', 'default', 'default'
console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn());
mockFn.mockName(value)
接受在测试结果输出中使用的字符串代替“jest.fn()”
以指示正在引用哪个模拟函数。
例如:
const mockFn = jest.fn().mockName('mockedFunction');
// mockFn();
expect(mockFn).toHaveBeenCalled();
会导致这个错误:
expect(mockedFunction).toHaveBeenCalled()
Expected mock function "mockedFunction" to have been called, but it was not called.
mockFn.mockReturnThis()
语法糖函数用于:
jest.fn(function () {
return this;
});
mockFn.mockReturnValue(value)
接受一个将在调用模拟函数时返回的值。
const mock = jest.fn();
mock.mockReturnValue(42);
mock(); // 42
mock.mockReturnValue(43);
mock(); // 43
mockFn.mockReturnValueOnce(value)
接受将在一次调用模拟函数时返回的值。可以链接,以便对模拟函数的连续调用返回不同的值。当没有更多mockReturnValueOnce
值可以使用时,调用将返回一个由 指定的值mockReturnValue
。
const myMockFn = jest
.fn()
.mockReturnValue('default')
.mockReturnValueOnce('first call')
.mockReturnValueOnce('second call');
// 'first call', 'second call', 'default', 'default'
console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn());
mockFn.mockResolvedValue(value)
语法糖函数用于:
jest.fn().mockImplementation(() => Promise.resolve(value));
在异步测试中模拟异步函数很有用:
test('async test', async () => {
const asyncMock = jest.fn().mockResolvedValue(43);
await asyncMock(); // 43
});
mockFn.mockResolvedValueOnce(value)
语法糖函数用于:
jest.fn().mockImplementationOnce(() => Promise.resolve(value));
用于解决多个异步调用的不同值:
test('async test', async () => {
const asyncMock = jest
.fn()
.mockResolvedValue('default')
.mockResolvedValueOnce('first call')
.mockResolvedValueOnce('second call');
await asyncMock(); // first call
await asyncMock(); // second call
await asyncMock(); // default
await asyncMock(); // default
});
mockFn.mockRejectedValue(value)
语法糖函数用于:
jest.fn().mockImplementation(() => Promise.reject(value));
用于创建始终拒绝的异步模拟函数:
test('async test', async () => {
const asyncMock = jest.fn().mockRejectedValue(new Error('Async error'));
await asyncMock(); // throws "Async error"
});
mockFn.mockRejectedValueOnce(value)
语法糖函数用于:
jest.fn().mockImplementationOnce(() => Promise.reject(value));
用法示例:
test('async test', async () => {
const asyncMock = jest
.fn()
.mockResolvedValueOnce('first call')
.mockRejectedValueOnce(new Error('Async error'));
await asyncMock(); // first call
await asyncMock(); // throws "Async error"
});
更多建议: