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
componentDidCatch
using a spy method. I am usingexpect.spyOn
there’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.console
but couldn’t mutejsdom
’s…Following up on @pizza-r0b’s technique, as mentioned here: https://github.com/airbnb/enzyme/issues/1255#issuecomment-352529487
expect
v23.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
,componentDidCatch
should already work. When usingshallow
on 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.error
as 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
extends
and 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!