React: Testing asynchronous setState of React

Created on 5 Dec 2017  路  3Comments  路  Source: facebook/react

Hello!!!

I'd read this article of Dave Ceddia: Snapshot Testing React Components with Jest. It's very useful but, I've got a big doubt about how Jest works (and I'm not the only one) and I don't understand how Jest can manage the asynchronous process when setState is called.

For instance, in the example of the article, increment is a function that calls setState and increments its value. Perfect. But, what about this test?

it('should render 2', () => {
  const component = renderer.create(<PositiveCounter/>);
  component.getInstance().increment();
  component.getInstance().increment();
  expect(component.toJSON()).toMatchSnapshot();
});

How can we assure that the expect will be called after the setState calls will be ended? And what about the second call of increment?

I strongly believe that I've got a misconception about this process, but I'm not the only one. Any help will be very well received.

Thanks a lot in advance!

PS: Redirected from https://github.com/facebook/jest/issues/5015

Most helpful comment

React 16 uses synchronous rendering by default so no, it won't fail.

There are also (AFAIK) no plans to enable async rendering in tests. It is an optimization for real rendering, and I don't think it would be valuable in a testing context.

All 3 comments

setState is not asynchronous in the way we usually mean in JavaScript. That is is to say that calls don't actually happen on another tick of the event loop, so from the outside of a react tree everything looks synchronous. What I mean by that is that setState calls may be batched together, so each call enqueues some update, but the update isn't processed until its that components "turn". Now that may actually be changing (changed?) with fibers async rendering, which is _actually_ async in the way we usually mean. For that I think we'll need some top level hooks to catch when a component is done rendering for realz.

Thanks a lot @jquense for your quicks answer! If I have understood properly, that means that this example will work with React 15 but it maybe will fail with React 16. Isn't it?

React 16 uses synchronous rendering by default so no, it won't fail.

There are also (AFAIK) no plans to enable async rendering in tests. It is an optimization for real rendering, and I don't think it would be valuable in a testing context.

Was this page helpful?
0 / 5 - 0 ratings