Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

node.js - Jest: tests can't fail within setImmediate or process.nextTick callback

I'm trying to write a test for a React component that needs to complete an asynchronous action in its componentWillMount method. componentWillMount calls a function, passed as a prop, which returns a promise, and I mock this function in my test.

This works fine, but if a test fails in a call to setImmediate or process.nextTick, the exception isn't handled by Jest and it exits prematurely. Below, you can see I even try to catch this exception, to no avail.

How can I use something like setImmediate or nextTick with Jest? The accepted answer to this question is what I'm trying to implement unsuccessfully: 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);
  }
});

Jest v18.1.0

Node v6.9.1

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Another potentially cleaner solution, using async/await and leveraging the ability of jest/mocha to detect a returned promise:

// 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);
});

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...