我有unhandledRejection
和uncaughtException
s的处理程序:
bin.js
['unhandledRejection', 'uncaughtException'].forEach(event => {
process.on(event, err => logger.error(err));
});
现在我想用jest
测试它们:
bin.test.js
const bin = require('../bin');
test('catches unhandled rejections', async () => {
const error = new Error('mock error');
await Promise.reject(error);
expect(logger.error).toHaveBeenCalledWith(error);
});
test('catches uncaught exceptions', () => {
const error = new Error('mock error');
throw error;
expect(logger.error).toHaveBeenCalledWith(error);
});
但是jest
只是告诉我测试中存在错误:
●捕获未处理的拒绝
mock error 8 | // https://github.com/facebook/jest/issues/5620 9 | test('catches unhandled rejections', async () => { > 10 | const error = new Error('mock error'); | ^ 11 | await Promise.reject(error); 12 | expect(logger.error).toHaveBeenCalledWith(error); 13 | }); at Object.<anonymous>.test (test/bin.test.js:10:17)
●捕获未捕获的异常
mock error 14 | 15 | test('catches uncaught exceptions', () => { > 16 | const error = new Error('mock error'); | ^ 17 | throw error; 18 | expect(logger.error).toHaveBeenCalledWith(error); 19 | }); at Object.<anonymous>.test (test/bin.test.js:16:17)
有没有办法对此进行测试?
这可能与以下内容有关:https://github.com/facebook/jest/issues/5620
答案 0 :(得分:1)
我的测试策略是使用 jest.spyOn(object, methodName) 将 spy 安装到 process.on()
和 logger.error
方法上。这样做之后,这些方法都没有副作用。然后,您可以在隔离的环境中测试您的代码逻辑。
此外,还有几点需要注意:
require('./bin')
语句之前的函数。因为当你加载 bin.js
模块时,代码会被执行。beforeEach
挂钩中使用 jest.resetModules() 来重置模块注册表 - 所有必需模块的缓存。为什么?因为 require()
缓存其结果。因此,第一次需要一个模块时,它的初始化代码就会运行。之后,缓存只返回 module.exports
的值,无需再次运行初始化代码。但是我们有两个测试用例,我们希望模块范围内的代码被执行两次。现在,这是示例:
bin.js
:
const logger = require('./logger');
['unhandledRejection', 'uncaughtException'].forEach((event) => {
process.on(event, (err) => logger.error(err));
});
logger.js
:
const logger = console;
module.exports = logger;
bin.test.js
:
const logger = require('./logger');
describe('52493145', () => {
beforeEach(() => {
jest.resetModules();
});
afterEach(() => {
jest.restoreAllMocks();
});
test('catches unhandled rejections', () => {
const error = new Error('mock error');
jest.spyOn(process, 'on').mockImplementation((event, handler) => {
if (event === 'unhandledRejection') {
handler(error);
}
});
jest.spyOn(logger, 'error').mockReturnValueOnce();
require('./bin');
expect(process.on).toBeCalledWith('unhandledRejection', expect.any(Function));
expect(logger.error).toHaveBeenCalledWith(error);
});
test('catches uncaught exceptions', () => {
const error = new Error('mock error');
jest.spyOn(process, 'on').mockImplementation((event, handler) => {
if (event === 'uncaughtException') {
handler(error);
}
});
jest.spyOn(logger, 'error').mockReturnValueOnce();
require('./bin');
expect(process.on).toBeCalledWith('uncaughtException', expect.any(Function));
expect(logger.error).toHaveBeenCalledWith(error);
});
});
单元测试结果:
PASS examples/52493145/bin.test.js
52493145
✓ catches unhandled rejections (5 ms)
✓ catches uncaught exceptions (1 ms)
-----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
bin.js | 100 | 100 | 100 | 100 |
logger.js | 100 | 100 | 100 | 100 |
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 2.73 s, estimated 4 s
源代码:https://github.com/mrdulin/jest-v26-codelab/tree/main/examples/52493145
答案 1 :(得分:-2)
将其放入try catch中将有所帮助:
const error = new Error('mock error');
尝试{
await Promise.reject(error);
} 抓住(错误){
expect(logger.error).toHaveBeenCalledWith(error);
}