Ad

ReactWrapper::state() Can Only Be Called On Class Components Unit Testing Jest And Enzyme

Writing unit testing in react using jest and enzyme. While checking with a component state , it throws an error "ReactWrapper::state() can only be called on class components ".

import React from 'react';
import { mount } from 'enzyme';
import expect from 'expect';
import CustomerAdd from '../CustomerAdd'
import MUITheme from '../../../../Utilities/MUITheme';
import { ThemeProvider } from '@material-ui/styles';

describe('<CustomerAdd />', () => {
    const wrapper = mount(
        <ThemeProvider theme={MUITheme}>
          <CustomerAdd {...mockProps}></CustomerAdd>
        </ThemeProvider>
        );
        test('something', () => {
            expect(wrapper.find(CustomerAdd).state('addNewOnSubmit')).toEqual(true);
        });
});

In the above code CustomerAdd Component is class component.I don't what wrong with my code. Can any one help me out of this problem. Thanks in advance.

Ad

Answer

So your default export

export default withStyles(styles)(CustomerAdd);

exports functional(HOC) wrapper about your class-based component. And it does not matter if name of class and import in

import CustomerAdd from '../CustomerAdd'

are equal. Your test imports wrapped version and after calling .find(CustomerAdd) returns that HOC not your class. And you're unable to work with instance.

Short time solution: export class directly as named export.

export class CustomerAdd extends React.Component{
  ...
}

export default withStyles(styles)(CustomerAdd);

Use named import in your tests:

import { CustomerAdd } from '../CusomerAdd';

Quick'n'dirty solution: use .dive to access your underlying class-based component:

expect(wrapper.find(CustomerAdd).dive().state('addNewOnSubmit')).toEqual(true);

It's rather antipattern since if you add any additional HOC in your default export you will need to monkey-patch all related tests with adding appropriate amount of .dive().dive()....dive() calls.

Long-term solution: avoid testing state, it's implementation details.

Instead focus on validating what's been rendered. Then you are safe in case of lot of different refactoring technics like replacing class with functional component, renaming state/instance members, lifting state up, connecting component to Redux etc.

Ad
source: stackoverflow.com
Ad