Jest测试承诺解决方案和事件循环滴答

时间:2018-03-21 11:37:08

标签: javascript node.js promise jest

对于我使用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根本没有被调用),我想因为承诺尚未解决。

我在这里做错了吗?我可以让事件循环在测试中打勾吗?

1 个答案:

答案 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);
      });
   });
});