Reputation: 85
I have built an error handler like this:
const logger = require('./logger');
module.exports = () => {
process.on('uncaughtException', (err) => {
logger.error(err.message, err);
process.exit(1);
});
process.on('unhandledRejection', (err) => {
throw err;
});
};
Now I want to unit test this, mainly the first event listener. My current test looks like this:
const logger = require('../../utils/logger');
require('../../utils/unhandledErrors')();
describe('Uncaught Exceptions', () => {
it('should log the exception and exit the process', () => {
process.exit = jest.fn();
logger.error = jest.fn();
jest.fn(() => {
throw new Error('fake error');
})();
expect(logger.error).toBeCalledTimes(1);
expect(process.exit).toBeCalledTimes(1);
expect(process.exit).toBeCalledWith(1);
});
});
The code above fails at throw new error line with no useful information logged to console by jest despite the --verbose flag.
Any suggestions on how to unit test such modules? I have looked through the link below but found nothing.
How to test a unhandledRejection / uncaughtException handler with jest
Upvotes: 1
Views: 2574
Reputation: 102577
My test strategy is to install spy onto process.on()
, process.exit()
and console.error
methods using jest.spyOn(object, methodName). After doing this, these methods have no side effects. Then, you can test your code logic in an isolated environment.
E.g.
unhandledErrors.js
:
module.exports = () => {
process.on('uncaughtException', (err) => {
console.error(err.message);
process.exit(1);
});
process.on('unhandledRejection', (err) => {
throw err;
});
};
unhandledErrors.test.js
:
const unhandledErrors = require('./unhandledErrors');
describe('65386298', () => {
afterEach(() => {
jest.restoreAllMocks();
});
it('should handle uncaughtException', () => {
const mError = new Error('Server internal error');
jest.spyOn(process, 'on').mockImplementation((event, handler) => {
if (event === 'uncaughtException') {
handler(mError);
}
});
jest.spyOn(console, 'error').mockReturnValueOnce();
jest.spyOn(process, 'exit').mockReturnValueOnce();
unhandledErrors();
expect(process.on).toBeCalledWith('uncaughtException', expect.any(Function));
expect(process.exit).toBeCalledWith(1);
expect(console.error).toBeCalledWith('Server internal error');
});
it('should handle unhandledRejection', () => {
const mError = new Error('dead lock');
jest.spyOn(process, 'on').mockImplementation((event, handler) => {
if (event === 'unhandledRejection') {
handler(mError);
}
});
expect(() => unhandledErrors()).toThrowError('dead lock');
expect(process.on).toBeCalledWith('unhandledRejection', expect.any(Function));
});
});
unit test result:
PASS examples/65386298/unhandledErrors.test.js
65386298
✓ should handle uncaughtException (3 ms)
✓ should handle unhandledRejection (1 ms)
--------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
--------------------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
unhandledErrors.js | 100 | 100 | 100 | 100 |
--------------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 5.201 s
Upvotes: 5