score:2

The problem is indeed React's error handling prevents the error from bubbling up to the top-level, where Jasmine can detect it. Two possible workarounds:

Monkeypatch console.error to actually throw

console.error = msg => { throw new Error(msg); };

This is obviously hack and would break if React changed to use a different approach for error reporting. stijndepestel's answer is a more robust approach to this.

Create an error boundary just for testing

let errorInfo = null;
class ErrorBoundary extends React.PureComponent {
    state = {hasError: false};

    componentDidCatch(err, info) {
        errorInfo = [err, info]
        this.setState({hasError: true});
    }

    render() {
        if (!this.state.hasError)
            return React.Children.only(this.props.children);
        return 'Errored';
    }
}

You can then wrap your test in a handler like this one and then assert that errorInfo is not null and that it contains an error as you expect

score:6

I have had a similar problem with the virtual-console from jsdom printing the error instead of throwing it. As far as I know, there is no way for Jest or any other testing framework to prevent code from printing to the console.

I have fixed this by replacing the listener that is responsible for printing to the console. The following code is run in a file which is configured in the setupFiles in the Jest configuration.

// There should be a single listener which simply prints to the 
// console. We will wrap that listener in our own listener.
const listeners = window._virtualConsole.listeners("jsdomError");
const originalListener = listeners && listeners[0];

window._virtualConsole.removeAllListeners("jsdomError");

window._virtualConsole.addListener("jsdomError", (error) => {
  if (error.type !== "not implemented" && originalListener) {
    originalListener(error);
  }
  // swallow
});

As you can see, in our case the error that was printed to the console (multiple times, as it was a side effect, and not the main purpose of our test) was a 'not-implemented' error. So it is only those kinds of errors that this code will swallow.

This solution is not ideal, but it will keep the logs cleaner.

PS: If you want to reduce the risk of swallowing 'real' errors, you might be able to use this trick in the before method of your test suite and use the after method to reset the original behaviour.


Related Query

More Query from same tag