模擬函數(shù)也被稱為“間諜”,因?yàn)樗鼈冏屇憧梢员O(jiān)視由其他代碼間接調(diào)用的函數(shù)的行為,而不僅僅是測(cè)試輸出。你可以使用?jest.fn()
?. 如果沒有給出實(shí)現(xiàn),模擬函數(shù)將?undefined
?在調(diào)用時(shí)返回。
返回通過調(diào)用設(shè)置的模擬名稱字符串?mockFn.mockName(value)
?。
包含對(duì)此模擬函數(shù)進(jìn)行的所有調(diào)用的調(diào)用參數(shù)的數(shù)組。數(shù)組中的每一項(xiàng)都是調(diào)用期間傳遞的參數(shù)數(shù)組。
例如:一個(gè)模擬函數(shù)f被調(diào)用了兩次,使用參數(shù)?f('arg1', 'arg2')
?,然后使用參數(shù)?f('arg3', 'arg4')
?,將有一個(gè)如下所示的?mock.calls
?數(shù)組:
[
['arg1', 'arg2'],
['arg3', 'arg4'],
];
一個(gè)數(shù)組,包含對(duì)此模擬函數(shù)進(jìn)行的所有調(diào)用的結(jié)果。此數(shù)組中的每個(gè)條目都是一個(gè)包含?type
?屬性和?value
?屬性的對(duì)象。?type
?將是以下之一:
'return'
? - 表示呼叫通過正常返回完成。'throw'
? - 表示通過拋出一個(gè)值來完成調(diào)用。'incomplete'
?- 表示呼叫尚未完成。如果你從模擬函數(shù)本身或從模擬調(diào)用的函數(shù)中測(cè)試結(jié)果,則會(huì)發(fā)生這種情況。value
?屬性包含拋出或返回的值。?當(dāng)?type === 'incomplete'
時(shí),value
?未定義?。
例如:一個(gè)模擬函數(shù)?f
?被調(diào)用了 3 次,返回?'result1'
?,拋出錯(cuò)誤,然后返回?'result2'
?,將有一個(gè)如下所示的?mock.results
?數(shù)組:
[
{
type: 'return',
value: 'result1',
},
{
type: 'throw',
value: {
/* Error instance */
},
},
{
type: 'return',
value: 'result2',
},
];
一個(gè)數(shù)組,其中包含已使用此模擬函數(shù)實(shí)例化的所有對(duì)象實(shí)例?new
?。
例如:已實(shí)例化兩次的模擬函數(shù)將具有以下?mock.instances
?數(shù)組:
const mockFn = jest.fn();
const a = new mockFn();
const b = new mockFn();
mockFn.mock.instances[0] === a; // true
mockFn.mock.instances[1] === b; // true
重置存儲(chǔ)在mockFn.mock.calls和mockFn.mock.instances數(shù)組中的所有信息。
當(dāng)你想要清理兩個(gè)斷言之間的模擬使用數(shù)據(jù)時(shí),這通常很有用。
當(dāng)心,mockClear將取代mockFn.mock,而不僅僅是mockFn.mock.calls和mockFn.mock.instances。因此,你應(yīng)該避免分配?mockFn.mock
?給其他變量,無(wú)論是臨時(shí)的還是非臨時(shí)的,以確保你不會(huì)訪問過時(shí)的數(shù)據(jù)。
clearMocks配置選項(xiàng)可用于在測(cè)試之間自動(dòng)清除模擬。
執(zhí)行所有mockFn.mockClear()操作,并刪除任何模擬的返回值或?qū)崿F(xiàn)。
當(dāng)你想要完全重置 mock 到初始狀態(tài)時(shí),這是有用。 (注意重置一個(gè) spy 將導(dǎo)致一個(gè)沒有返回值的函數(shù))。
當(dāng)心,?mockReset
?將取代?mockFn.mock
?,而不僅僅是mockFn.mock.calls和mockFn.mock.instances。因此,你該避免分配?mockFn.mock
?給其他變量,無(wú)論是臨時(shí)的還是非臨時(shí)的,以確保你不會(huì)訪問過時(shí)的數(shù)據(jù)。
執(zhí)行所有mockFn.mockReset()操作,并恢復(fù)原始(非模擬)實(shí)現(xiàn)。
當(dāng)你想在某些測(cè)試用例中模擬函數(shù)并在其他測(cè)試用例中恢復(fù)原始實(shí)現(xiàn)時(shí),這很有用。
請(qǐng)注意,?mockFn.mockRestore
?只有在使用?jest.spyOn
?. 因此,你必須在手動(dòng)分配?jest.fn()
?.
restoreMocks配置選項(xiàng)可用于在測(cè)試之間自動(dòng)恢復(fù)模擬。
接受一個(gè)應(yīng)該用作模擬實(shí)現(xiàn)的函數(shù)。模擬本身仍然會(huì)記錄進(jìn)入的所有調(diào)用和來自自身的實(shí)例——唯一的區(qū)別是當(dāng)模擬被調(diào)用時(shí),實(shí)現(xiàn)也會(huì)被執(zhí)行。
注意:?jest.fn(implementation)
?是 的簡(jiǎn)寫?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
?也可用于模擬類構(gòu)造函數(shù):
// 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);
接受一個(gè)函數(shù),該函數(shù)將用作對(duì)模擬函數(shù)的一次調(diào)用的模擬實(shí)現(xiàn)??梢枣溄樱员愣鄠€(gè)函數(shù)調(diào)用產(chǎn)生不同的結(jié)果。
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
當(dāng)模擬函數(shù)用完用 ?mockImplementationOnce
?定義的實(shí)現(xiàn)時(shí),它將執(zhí)行設(shè)置的默認(rèn)實(shí)現(xiàn),?jest.fn(() => defaultValue)
?或者?.mockImplementation(() => defaultValue)
?如果它們被調(diào)用:
const myMockFn = jest
.fn(() => 'default')
.mockImplementationOnce(() => 'first call')
.mockImplementationOnce(() => 'second call');
// 'first call', 'second call', 'default', 'default'
console.log(myMockFn(), myMockFn(), myMockFn(), myMockFn());
接受在測(cè)試結(jié)果輸出中使用的字符串代替?“jest.fn()”
?以指示正在引用哪個(gè)模擬函數(shù)。
例如:
const mockFn = jest.fn().mockName('mockedFunction');
// mockFn();
expect(mockFn).toHaveBeenCalled();
會(huì)導(dǎo)致這個(gè)錯(cuò)誤:
expect(mockedFunction).toHaveBeenCalled()
Expected mock function "mockedFunction" to have been called, but it was not called.
語(yǔ)法糖函數(shù)用于:
jest.fn(function () {
return this;
});
接受一個(gè)將在調(diào)用模擬函數(shù)時(shí)返回的值。
const mock = jest.fn();
mock.mockReturnValue(42);
mock(); // 42
mock.mockReturnValue(43);
mock(); // 43
接受將在一次調(diào)用模擬函數(shù)時(shí)返回的值??梢枣溄?,以便對(duì)模擬函數(shù)的連續(xù)調(diào)用返回不同的值。當(dāng)沒有更多?mockReturnValueOnce
?值可以使用時(shí),調(diào)用將返回一個(gè)由 指定的值?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());
語(yǔ)法糖函數(shù)用于:
jest.fn().mockImplementation(() => Promise.resolve(value));
在異步測(cè)試中模擬異步函數(shù)很有用:
test('async test', async () => {
const asyncMock = jest.fn().mockResolvedValue(43);
await asyncMock(); // 43
});
語(yǔ)法糖函數(shù)用于:
jest.fn().mockImplementationOnce(() => Promise.resolve(value));
用于解決多個(gè)異步調(diào)用的不同值:
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
});
語(yǔ)法糖函數(shù)用于:
jest.fn().mockImplementation(() => Promise.reject(value));
用于創(chuàng)建始終拒絕的異步模擬函數(shù):
test('async test', async () => {
const asyncMock = jest.fn().mockRejectedValue(new Error('Async error'));
await asyncMock(); // throws "Async error"
});
語(yǔ)法糖函數(shù)用于:
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"
});
更多建議: