对于我使用promises的代码,我有一个失败的Jest测试用例。在测试完成后,看起来承诺的解决方案正在发生,这意味着我无法检查我的承诺解析代码是否已经执行。
感觉我需要让事件循环勾选,以便解决承诺并执行解析代码,但是在Jest中找不到任何可以做到的事情。
这是一个示例案例。要测试的代码:
const Client = require('SomeClient');
module.exports.init = () => {
Client.load().then(() => {
console.log('load resolved');
setTimeout(() => {
console.log('load setTimeout fired, retrying init');
module.exports.init();
}, 1000);
});
};
测试代码:
jest.useFakeTimers();
const mockLoad = jest.fn().mockImplementation(() => Promise.resolve());
jest.mock('SomeClient', () => {
return {
load: mockLoad
};
}, { virtual: true });
const promiseTest = require('./PromiseTest');
describe('SomeClient Promise Test', () => {
it('retries init after 10 secs', () => {
promiseTest.init();
expect(mockLoad).toHaveBeenCalledTimes(1);
expect(setTimeout).toHaveBeenCalledTimes(1); // <-- FAILS - setTimeout has not been called
jest.runAllTimers();
expect(mockLoad).toHaveBeenCalledTimes(2);
});
});
expect(setTimeout).toHaveBeenCalledTimes(1);
断言失败(setTimeout
根本没有被调用),我想因为承诺尚未解决。
我在这里做错了吗?我可以让事件循环在测试中打勾吗?
答案 0 :(得分:2)
要勾选测试中的事件循环,您应该使其异步。 在GitHub上建议了一个很好的解决方法。
按照建议flushPromises
function flushPromises() {
return new Promise(resolve => setImmediate(resolve));
}
您的测试看起来像
describe('SomeClient Promise Test', () => {
it('retries init after 10 secs', () => {
promiseTest.init();
expect(mockLoad).toHaveBeenCalledTimes(1);
// notice return so jest knows that the test is asynchronous
return flushPromises()
.then(() => {
expect(setTimeout).toHaveBeenCalledTimes(1);
jest.runAllTimers();
expect(mockLoad).toHaveBeenCalledTimes(2);
});
});
});