enzyme: Enzyme 3 couldn't test component when ComponentDidCatch happend
My Component:
class Error extends React.Component {
render() {
throw new Error('ErrorMessage');
return <div />;
}
}
class App extends React.Component {
constructor() {
super();
this.state = {
hasError: false,
error: null,
errorInfo: null
}
}
componentDidCatch(error, info) {
this.setState({
hasError: true,
error,
errorInfo: info
});
}
render() {
const { hasError } = this.state;
if (this.state.hasError) {
return <div className="error-view">error view</div>
}
return <Error />
}
}
My test:
const app = mount(<App />);
const errorTip = app.setState({
hasError: true,
});
expect(app.find('.error-view').length).to.equal(1);
When app is mount,app throws the error and I couldn’t get the app to test the error view. How do I solve it?
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 12
- Comments: 17 (3 by maintainers)
You can test
componentDidCatchusing a spy method. I am usingexpect.spyOnthere’s alsosinon. Here’s is a working example of testingcomponentDidCatch:@QuentinRoy I had the same issue and was able to mute jsdom’s console by doing:
jest.spyOn(window._virtualConsole, 'emit').mockImplementation(() => false);in a beforeEach. That might be a terrible idea? But it doesn’t seem to have broken anything…@realseanp Any idea how to remove the annoying console logging? I was able to mute react’s by mocking
global.consolebut couldn’t mutejsdom’s…Following up on @pizza-r0b’s technique, as mentioned here: https://github.com/airbnb/enzyme/issues/1255#issuecomment-352529487
expectv23.5.0 does not appear to have aspyOn()method (it was donated to Jest, so that may account for the API difference?). I would like to avoid add another devDependency to my project, so I’m going to avoid sinon for now.Instead, I’ve found that the following technique appears to work with
expect().toThrowError()in Jest 23.5.0, Enzyme 3.4.1, and React 16.4.2.Spoiler: the technique involves calling Enzyme’s
ReactWrapper.html()and expecting an error to be thrown. You can also do this with Enzyme’sShallowWrapper.html().With
mount()Note: you may still want to suppress
console.error()output, as @jessicarobins suggested above: https://github.com/airbnb/enzyme/issues/1255#issuecomment-377311872As an alternative that also avoids
console.error()output, consider usingshallow()anddive()with this technique:With
shallow()anddive()When using
mount,componentDidCatchshould already work. When usingshallowon an error boundary, nothing is being rendered that could throw, so there’s no way to trigger the error.#1797 will add proper support for this.
This workaround only tests to make sure that
componentDidCatch, which is definitely better then nothing. Ideally enzyme should also be able to test that the rendered output if there is an error, and ensure that it was rendered correctly as well.@ljharb is there a milestone/checklist anywhere of react features not yet supported?
@jessicarobins That’s a good tip! For others reading this, if you want to mute all error output, silence
console.erroras that’s the function used by jsdom and doesn’t rely on jsdom interface which could change.@lesbaa Yes in general I entirely agree. Though in this case this is a message from React warning about the exact behaviour being under scrutiny. So it is really just confusing noise in the test output. I wish react gave a way to disable this warning so that we do not have to mute all output, but it does not seem to be a way to do that yet.
@kohlmannj thanks , but when i use
extendsand throw error in constructor,code is here.
@realseanp Nice. I did the same with jest.spyOn() and that got my coverage up to 100%. Thank you!