How I Fixed: TypeError: Invalid attempt to destructure non-iterable instance

This morning I hit upon a really annoying problem whilst trying to write a basic test for a React component.

The internals of the component are not important to the issue I was facing.

Here’s the outcome:

 FAIL  src/components/my-component.spec.jsx
  ● MyComponent › should dispatch the expected actions when clicking the important button

    TypeError: Invalid attempt to destructure non-iterable instance

      14 |
    > 15 | const MyComponent = ({ some, props }) => {
         |                                                             ^
      16 |   console.log('wtf', { some, props });
      17 |   const ... // do stuff here
      18 |

      at _nonIterableRest (node_modules/babel-preset-react-app/node_modules/@babel/runtime/helpers/nonIterableRest.js:2:9)
      at _slicedToArray (node_modules/babel-preset-react-app/node_modules/@babel/runtime/helpers/slicedToArray.js:8:65)
      at MyComponent (src/components/my-component.jsx:15:61)

What frustrated me was that the first it block was working. And then the second block would not work.

I could xit the first it, and then the second it would work / pass. But together, they would not play nicely.

The reason for this is something that’s caught me out several times previously, but something I keep forgetting about. Here we go:

describe('MyComponent', () => {
  afterEach(() => {
    jest.resetAllMocks();
    cleanup();
  });

The issue is the use of jest.resetAllMocks();.

Here’s what it should be:

describe('MyComponent', () => {
  afterEach(() => {
    jest.clearAllMocks();
    cleanup();
  });

In case you missed it, switch resetAllMocks for clearAllMocks.

The reasoning, in my case is that I had declared a .mockImplementation elsewhere in my test, and a call to resetAllMocks wipes out that mock implementation.

At least, that’s my understanding of it.

For more details see the docs for the difference between resetAllMocks and clearAllMocks.