开玩笑:在setImmediate或process.nextTick回调中测试不会失败

Ale*_*son 5 node.js jasmine reactjs jestjs

我正在尝试为需要在其componentWillMount方法中完成异步操作的React组件编写测试。componentWillMount调用作为prop传递的函数,该函数返回promise,然后在测试中模拟该函数。

这可以正常工作,但是如果在调用setImmediate或时测试失败process.nextTick,则Jest不会处理该异常,并且该异常会过早退出。在下面,您可以看到我什至试图捕获此异常,但无济于事。

我如何使用像setImmediate或者nextTick用玩笑?这个问题的公认答案是我试图实现失败的目标:React Enzyme-Test`componentDidMount` Async Call

it('should render with container class after getting payload', (done) => {
  let resolveGetPayload;
  let getPayload = function() {
    return new Promise(function (resolve, reject) {
      resolveGetPayload = resolve;
    });
  }
  const enzymeWrapper = mount(<MyComponent getPayload={getPayload} />);

  resolveGetPayload({
    fullname: 'Alex Paterson'
  });

  try {
    // setImmediate(() => {
    process.nextTick(() => {
      expect(enzymeWrapper.hasClass('container')).not.toBe(true); // Should and does fail
      done();
    });
  } catch (e) {
    console.log(e); // Never makes it here
    done(e);
  }
});
Run Code Online (Sandbox Code Playgroud)

笑话v18.1.0

节点v6.9.1

Off*_*rmo 8

另一个可能更干净的解决方案,使用 async/await 并利用 jest/mocha 的能力来检测返回的承诺:

// async test utility function
function currentEventLoopEnd() {
  return new Promise(resolve => setImmediate(resolve));
}

it('should render with container class after getting payload', async () => {
  
  // mock the API call in a controllable way,
  // starts out unresolved
  let resolveGetPayload; // <- call this to resolve the API call
  let getPayload = function() {
    return new Promise(function (resolve, reject) {
      resolveGetPayload = resolve;
    });
  }
  
  // instanciate the component under state with the mock
  const enzymeWrapper = mount(<MyComponent getPayload={getPayload} />);
  expect(enzymeWrapper.hasClass('container')).not.toBe(true);

  resolveGetPayload({
    fullname: 'Alex Paterson'
  });

  await currentEventLoopEnd(); // <-- clean and clear !

  expect(enzymeWrapper.hasClass('container')).toBe(true);
});
Run Code Online (Sandbox Code Playgroud)


Jam*_*son 2

一些需要注意的事项;

  • process.nextTick 异步的,因此 try/catch 将无法捕获它。
  • Promise即使您在 Promise 中运行的代码是同步的,也会解析/拒绝异步。

尝试一下

it('should render with container class after getting payload', (done) => {
    const getPayload = Promise.resolve({
        fullname: 'Alex Paterson'
    });
    const enzymeWrapper = mount(<MyComponent getPayload={getPayload} />);

    process.nextTick(() => {
        try {
            expect(enzymeWrapper.hasClass('container')).not.toBe(true);
        } catch (e) {
            return done(e);
        }
        done();
    });
});
Run Code Online (Sandbox Code Playgroud)

  • 它应该是`done.fail(e)`。如果您执行“done(e)”,测试将通过,因为“done()”不接受参数。Jasmine 页面上记录了“fail”函数:[done.fail 函数](https://jasmine.github.io/2.3/introduction#section-54) (2认同)