In my create-react-app, I am trying to test a component that does multiple setState when mounted.
class MyComponent extends React.Component { state = { a: undefined, b: undefined, c: undefined, }; fetchA() {
In my test, I am doing something like this, trying to end setState in componentDidUpdate before making statements.
import { mount } from 'enzyme'; describe('MyComponent', () => { const fakeA = Promise.resolve('a'); const fakeB = Promise.resolve('b'); const fakeC = Promise.resolve('c'); MyComponent.prototype.fetchA = jest.fn(() => fakeA); MyComponent.prototype.fetchB = jest.fn(() => fakeB); MyComponent.prototype.fetchC = jest.fn(() => fakeC); it('sets needed state', async () => { const wrapper = mount(<MyComponent />); await Promise.all([ fakeA, fakeB, fakeC ]); expect(wrapper.state()).toEqual({ a: 'a', b: 'b', c: 'c', }); }); });
Here is the interesting part: My test above will fail because the last call to setState (in componentDidUpdate ) did not complete when this statement was made. state.a installed state.a this time, but state.b and state.c are not yet installed.
The only way I could get it to work is to insert await Promise.resolve(null) just before the statement, to give the last setState an extra tick / cycle. It looks too hacky.
Another thing I've tried is to wrap the statement in setImmediate() , which works fine as long as that statement has passed. If it fails, it will complete the entire test due to an uncaught error.
Can anyone solve this problem?
asynchronous unit-testing reactjs jestjs enzyme
vleong
source share