loading...

What's the issue with the MockedProvider component?

teachingtls profile image teachingtechleads ・1 min read

Hey DEV community, I'm struggling with why the react-dom library is yelling at me in my tests. So much so, that I spun up a git repo in order to demonstrate what the issue is that I'm facing.

If you pull down the repo, you can see the console warning, even though I'm getting passing tests.

Quick overview of the test:

  • Wrap a component in a
  • Provide the MockedProvider with a mock query/response
  • Mount said component via enzyme
  • await the data to refresh and run my assertions

Every time that I run the tests, I get the following console warning, in bright red colors:

  Warning: An update to Query inside a test was not wrapped in act(...).

    When testing, code that causes React state updates should be wrapped into act(...):

    act(() => {
      /* fire events that update state */
    });
    /* assert on the output */

    This ensures that you're testing the behavior the user would see in the browser. Learn more at https://fb.me/react-wrap-tests-with-act
        in Query (at App.tsx:37)
        in div (at App.tsx:36)
        in App (at App.test.tsx:51)
        in ApolloProvider (created by MockedProvider)
        in MockedProvider (created by WrapperComponent)
        in WrapperComponent

I even followed the link and used the act() function referenced. I actually left that third test in there, because it throws the same warning.

So, is it that I'm using Enzyme to mount instead of React Test Renderer? Anybody have some tips? I'm open to pull requests with best practices for testing.

Posted on by:

teachingtls profile

teachingtechleads

@teachingtls

Dedicated Tech Lead and Author of https://teachingtechleads.com

Discussion

pic
Editor guide
 

Hi there!

waitForExpect is not wrapping your callback with act (like it should in react), thus causing that error.

My recommendation would be to use @testing-library/react wait function.

await wait(() => {
      wrapper.update();
      expect(wrapper.find('.productName').length).toEqual(2);
    });

This approach should make your second and third test warnings go away.

As for the first test (which also throws this warning)

    // const wrapper = ...
    expect(wrapper.exists()).toEqual(true);
    expect(wrapper.text()).toEqual('Loading store data...');
   // warning actually is being thrown after this line /\

So what actually happens? Well, you make an assertion for loading state which passes, then, very loosely named, next tick happens and state updates to an error (asynchronously) and the test finishes. What you have to do in such situations is to queue a task (task-queue) that contains an act, after the assertion, like so:

    // const wrapper = ...
    expect(wrapper.exists()).toEqual(true);
    expect(wrapper.text()).toEqual('Loading store data...');
    await act(async () => await Promise.resolve());

The error will go await. act will put your callback inside batch update when React flushes tasks, guaranteeing that any left-overs async updates are taken care of.

You should give @testing-library/react a shot! in my opinion, it's much better than enzyme.

I'm not an expert and the things I said about the task queue and stuff may be wrong. It's just how I think about it.

Cheers!

 

Thanks for the tip, Wojciech.

I looked into the library you referenced for a few minutes and found that @testing-library/react has a wait() function, which is documented as a small wrapper around the await-for expect module.

I don't think that is much gained from using it. There's even a callout in the readme about suppressing the very warning that I'm complaining about.

 

Wojciech, if I'm following your notes correctly, the difference is in how the testing-library/react appends to the action queue the callback versus how wait-for-expect isn't allowing the other asynchronous tasks to complete.

Sorry for being stubborn before, the event loop is still a new concept to me. Thanks for the overall help. I was able to put together a simple commit that swaps the libraries and gets me to a more green test suite.

 

Thanks again for the updated response.

I'll go back through and update my tests to try following this pattern. Will update when I have some new findings.