如何在 Jest 中重置测试之间的模拟通话录音?



我正在学习Jest和现代JavaScript,并试图测试一段代码。我的测试分组在一个describe()容器中,我想在测试之间重置模拟(和模拟计数(。Stack Overflow上似乎有一些问题涉及重置或清除模拟数据,但它们似乎在我的情况下不起作用,而且我对JS太新了,无法理解可能存在的区别。

这是我的SUT(source.js(:

module.exports = async function(delay) {
let query;
let ok;
for (let i = 0; i < 5; i++) {
query = context.functions.execute('getNextQuery');
if (query) {
ok = context.functions.execute('runQuery', query);
if (ok) {
context.functions.execute('markQueryAsRun', query.id);
}
} else {
break;
}
// Be nice to the API
await sleep(delay);
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
};

以下是测试:

const findAndRunQueries = require('./source');
describe('Some tests for findAndRunQueries', () => {
let globalMocks = {};
// context.functions.execute() becomes a mock
global.context = {
functions: {
execute: jest.fn((funcName, ...params) => {
// This calls a mock that we set up per test
return globalMocks[funcName](...params);
})
}
};
test('No queries need to be run', async () => {
// Don't need to mock other funcs if this one is falsey
setGlobalMock('getNextQuery', () => {
return null;
});
await findAndRunQueries(0);
// Ensure only getNextQuery is called
expect(getNthMockFunctionCall(0)[0]).toBe('getNextQuery');
expect(countMockFunctionCalls()).toBe(1);
});
test('One query needs to be run', async () => {
let callCount = 0;
// Return an object on the first run, null on the second
setGlobalMock('getNextQuery', () => {
if (callCount++ === 0) {
return {
something: 'fixme'
};
} else {
return null;
}
});
setGlobalMock('runQuery', (query) => {
return true;
});
setGlobalMock('markQueryAsRun', (queryId) => {
// Does not need to return anything
});
await findAndRunQueries(0);
// Ensure each func is called
expect(getNthMockFunctionCall(0)[0]).toBe('getNextQuery');
expect(getNthMockFunctionCall(1)[0]).toBe('runQuery');
expect(getNthMockFunctionCall(2)[0]).toBe('markQueryAsRun');
// We have a 4th call here, which returns null to terminate the loop early
expect(getNthMockFunctionCall(3)[0]).toBe('getNextQuery');
// Ensure there is no extra calls
expect(countMockFunctionCalls()).toBe(4);
});
function setGlobalMock(funcName, func) {
globalMocks[funcName] = func;
}
function getNthMockFunctionCall(n) {
return global.context.functions.execute.mock.calls[n];
}
function countMockFunctionCalls() {
return global.context.functions.execute.mock.calls.length;
}
});

这里有两个测试,No queries need to be runOne query needs to be run。错误在第二个,我怀疑正在发生的事情是模拟录音从第一次测试中持续存在,并破坏了结果。

我已经通过自行运行此测试来确认这一点:

node node_modules/jest/bin/jest.js -t 'One query needs to be run'

但是,如果我运行两个测试,如下所示:

node node_modules/jest/bin/jest.js functions/findAndRunQueries

然后我得到一个失败:

● Some tests for findAndRunQueries › One query needs to be run
expect(received).toBe(expected) // Object.is equality
Expected: "runQuery"
Received: "getNextQuery"
53 |         // Ensure each func is called
54 |         expect(getNthMockFunctionCall(0)[0]).toBe('getNextQuery');
> 55 |         expect(getNthMockFunctionCall(1)[0]).toBe('runQuery');
|                                              ^
56 |         expect(getNthMockFunctionCall(2)[0]).toBe('markQueryAsRun');
57 | 
58 |         // We have a 4th call here, which returns null to terminate the loop early
at Object.test (functions/findAndRunQueries/findAndRunQueries.test.js:55:46)
Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 passed, 2 total
Snapshots:   0 total
Time:        0.637s, estimated 1s
Ran all test suites matching /functions/findAndRunQueries/i.

它说第二个测试(getNthMockFunctionCall(1)[0](中第二次调用中的第一个参数是getNextQuery,当我期待runQuery时。我认为这表明第一次测试的模拟结果仍然存在。

我尝试添加这个:

beforeAll(() => {
jest.clearAllMocks();
});

我相信开玩笑的说法中的"清除"和"重置"是不同的 - 清除只是重置计数,重置也会删除模拟实现。所以这是清除我想要的,但不幸的是这没有什么区别。

我还可以尝试哪些其他方法?

您可以尝试添加:

afterEach(() => {
jest.restoreAllMocks()
});

此外,最好使用beforeEach来定义重复使用的测试变量/模拟,以便为每个测试单独定义它们。

最新更新