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.
Jest can be used without Enzyme to render components and test with snapshots, Enzyme simply adds additional functionality. Enzyme can be used without Jest, however Enzyme must be paired with another test runner if Jest is not used.
Many people choose to use Jest and Enzyme together to test their React web applications. They use Jest as a test runner and assertion library, then use Enzyme to build the tests for their UI. This results in slimmer, cleaner testing code that's also easier to debug when a test breaks.
setState(state) => Self. A method to invoke setState() on the root component instance similar to how you might in the definition of the component, and re-renders. This method is useful for testing your component in hard to achieve states, however should be used sparingly.
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.
export class CustomerAdd extends React.Component{
...
}
export default withStyles(styles)(CustomerAdd);
Use named import in your tests:
import { CustomerAdd } from '../CusomerAdd';
.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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With