Testing error handling and exceptions in Jest is crucial for ensuring code robustness:
1. Testing Synchronous Function Errors:
javascripttest('throws error when invalid input', () => { expect(() => divide(10, 0)).toThrow(); expect(() => divide(10, 0)).toThrow('Division by zero'); expect(() => divide(10, 0)).toThrow(/zero/); });
2. Testing Promise Rejections:
javascripttest('rejects when API fails', async () => { await expect(fetchData()).rejects.toThrow('API Error'); }); // Or use .catch test('rejects when API fails', async () => { await expect(fetchData()).rejects.toEqual({ message: 'API Error' }); });
3. Testing Errors in Async Callbacks:
javascripttest('callback with error', (done) => { fetchData((err, data) => { expect(err).toBeInstanceOf(Error); expect(err.message).toBe('Network error'); done(); }); });
4. Testing Custom Error Types:
javascripttest('throws custom error', () => { expect(() => validate(null)).toThrow(ValidationError); });
5. Using try-catch for Testing:
javascripttest('handles error gracefully', async () => { try { await riskyOperation(); fail('Should have thrown an error'); } catch (error) { expect(error).toBeInstanceOf(Error); expect(error.message).toContain('failed'); } });
6. Testing Error Boundaries (React):
javascripttest('ErrorBoundary catches errors', () => { const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); render( <ErrorBoundary> <ThrowingComponent /> </ErrorBoundary> ); expect(screen.getByText('Something went wrong')).toBeInTheDocument(); consoleSpy.mockRestore(); });
Best Practices:
- Clearly test error messages and types
- Use
toThrow()to match error messages or regex - Test error handling logic, not just errors themselves
- Ensure cleanup of mocks and spies
- Test edge cases and invalid inputs