21
  • 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

6 Answers 6

27

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();
    })
Sign up to request clarification or add additional context in comments.

3 Comments

This is not what you were trying to check in your question posted above.My answer is the right solution to your problem.
This will cause the method to run twice.
@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.
17

Something like this should work for you:-

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

2 Comments

This was the best solution for me, particularly as I didn't want to shallow mount
Indeed; and if you have a setState in the component's didMount, you'll need to add wrapper.update(); before the expect.
4

Try this:

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

4 Comments

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"
what's app here?
@Pavan I think wrapper.update() was intended. --ref
btw, await won't do anything there unless your componentDidMount() returns a promise
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);
});

1 Comment

For anybody looking at this, use setTimeout instead of setImmediate.
0

Your test also needs to implement async, await.
For ex:

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

3 Comments

edited, have you tried the await when you execute the instance?, The await basically operates on a promise
if you can share your complete test
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
0

If you are using jest.useFakeTimers(); then you need to use

await jest.runAllTimersAsync();

instead of the flushPromises solution

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.