Testing with React's Jest and Enzyme when async componentDidMount

19,922

Solution 1

Solution:

1: use the async/await syntax.

2: Use mount (no shallow).

3: await async componentLifecycle.

For ex:

    test(' ',async () => {
      const wrapper = mount(
         <Foo />
      );
      await wrapper.instance().componentDidMount();
    })

Solution 2

Something like this should work for you:-

 describe('...', () => {
   test('...', async () => {
     const wrapper = await mount(<Foo/>);
     expect(wrapper.instance().bar).toBe(100);
   });
 });

Solution 3

Try this:

it('should do something', async function() {
  const wrapper = shallow(<Foo />);
  await wrapper.instance().componentDidMount();
  app.update();
  expect(wrapper.instance().bar).toBe(100);
});

Solution 4

None of the solutions provided here fixed all my issues. At the end I found https://medium.com/@lucksp_22012/jest-enzyme-react-testing-with-async-componentdidmount-7c4c99e77d2d which fixed my problems.

Summary

function flushPromises() {
    return new Promise(resolve => setImmediate(resolve));
}

it('should do someting', async () => {
    const wrapper = await mount(<Foo/>);
    await flushPromises();

    expect(wrapper.instance().bar).toBe(100);
});
Share:
19,922
Whj
Author by

Whj

Updated on June 24, 2022

Comments

  • Whj
    Whj almost 2 years
    • react:16.3.0-alpha.1
    • jest: "22.3.0"
    • enzyme: 3.3.0
    • typescript: 2.7.1

    code:

    class Foo extends React.PureComponent<undefined,undefined>{
       bar:number;
       async componentDidMount() {
         this.bar = 0;
         let echarts = await import('echarts'); // async import
         this.bar = 100;
       }
    }
    

    test:

    describe('...', () => {
      test('...', async () => {
        const wrapper = shallow(<Foo/>);
        const instance = await wrapper.instance();
        expect(instance.bar).toBe(100);
      });
    });
    

    Error:

    Expected value to be:
      100
    Received:
      0
    
  • Ignacio
    Ignacio about 6 years
    edited, have you tried the await when you execute the instance?, The await basically operates on a promise
  • Ignacio
    Ignacio about 6 years
    if you can share your complete test
  • VivekN
    VivekN about 6 years
    This is not what you were trying to check in your question posted above.My answer is the right solution to your problem.
  • Simon Keep
    Simon Keep almost 6 years
    This was the best solution for me, particularly as I didn't want to shallow mount
  • Max
    Max over 5 years
    After looking through google on this problem and trying to implement async componentDidMount through mount's enzyme. And "mount" way is not fit for react native project - I had a lot mistakes. This method helped me. And you don't need to install jsdom and use mount. "react": "16.4.1", "react-native": "0.56.0", "enzyme": "^3.4.4", "jest": "23.5.0"
  • Pavan
    Pavan over 5 years
    what's app here?
  • MustSeeMelons
    MustSeeMelons over 5 years
    This will cause the method to run twice.
  • cameck
    cameck over 5 years
    I don't think .instance() returns a promise, so I don't think await is doing anything there. TypeError: wrapper.instance(...).then is not a function
  • cameck
    cameck over 5 years
    @Pavan I think wrapper.update() was intended. --ref
  • cameck
    cameck over 5 years
    btw, await won't do anything there unless your componentDidMount() returns a promise
  • Marius
    Marius about 5 years
    @VivekN has the right solution. This will run "componentDidMount" twice. Any await after mounting will probably "solve" the problem, but it's not the right solution in my opinion.
  • Yann Dìnendal
    Yann Dìnendal almost 5 years
    Indeed; and if you have a setState in the component's didMount, you'll need to add wrapper.update(); before the expect.