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
.