Luk*_*kas 6 javascript unit-testing jestjs
我有unhandledRejections和uncaughtExceptions的处理程序:
bin.js
['unhandledRejection', 'uncaughtException'].forEach(event => {
process.on(event, err => logger.error(err));
});
Run Code Online (Sandbox Code Playgroud)
现在我想测试它们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);
});
Run Code Online (Sandbox Code Playgroud)
但jest只是告诉我测试中有错误:
●捕获未处理的拒绝
Run Code Online (Sandbox Code Playgroud)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)●捕获未捕获的异常
Run Code Online (Sandbox Code Playgroud)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)
有没有办法测试这个?
我的测试策略是使用jest.spyOn(object, methodName)安装间谍process.on()和logger.error方法。这样做之后,这些方法就没有副作用了。然后,您可以在隔离环境中测试代码逻辑。
除此之外,还有以下几点需要注意:
\nrequire(\'./bin\')。因为当你加载bin.js模块时,代码就会被执行。beforeEach来重置模块注册表 - 所有必需模块的缓存。为什么?因为require()缓存了它的结果。因此,第一次需要模块时,就会运行其初始化代码。之后,缓存只是返回 的值,module.exports而不再运行初始化代码。但是我们有两个测试用例,我们希望模块范围内的代码执行两次。现在,这是一个例子:
\nbin.js:
const logger = require(\'./logger\');\n\n[\'unhandledRejection\', \'uncaughtException\'].forEach((event) => {\n process.on(event, (err) => logger.error(err));\n});\nRun Code Online (Sandbox Code Playgroud)\nlogger.js:
const logger = console;\n\nmodule.exports = logger;\nRun Code Online (Sandbox Code Playgroud)\nbin.test.js:
const logger = require(\'./logger\');\n\ndescribe(\'52493145\', () => {\n beforeEach(() => {\n jest.resetModules();\n });\n afterEach(() => {\n jest.restoreAllMocks();\n });\n test(\'catches unhandled rejections\', () => {\n const error = new Error(\'mock error\');\n jest.spyOn(process, \'on\').mockImplementation((event, handler) => {\n if (event === \'unhandledRejection\') {\n handler(error);\n }\n });\n jest.spyOn(logger, \'error\').mockReturnValueOnce();\n require(\'./bin\');\n expect(process.on).toBeCalledWith(\'unhandledRejection\', expect.any(Function));\n expect(logger.error).toHaveBeenCalledWith(error);\n });\n\n test(\'catches uncaught exceptions\', () => {\n const error = new Error(\'mock error\');\n jest.spyOn(process, \'on\').mockImplementation((event, handler) => {\n if (event === \'uncaughtException\') {\n handler(error);\n }\n });\n jest.spyOn(logger, \'error\').mockReturnValueOnce();\n require(\'./bin\');\n expect(process.on).toBeCalledWith(\'uncaughtException\', expect.any(Function));\n expect(logger.error).toHaveBeenCalledWith(error);\n });\n});\nRun Code Online (Sandbox Code Playgroud)\n单元测试结果:
\n PASS examples/52493145/bin.test.js\n 52493145\n \xe2\x9c\x93 catches unhandled rejections (5 ms)\n \xe2\x9c\x93 catches uncaught exceptions (1 ms)\n\n-----------|---------|----------|---------|---------|-------------------\nFile | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s \n-----------|---------|----------|---------|---------|-------------------\nAll files | 100 | 100 | 100 | 100 | \n bin.js | 100 | 100 | 100 | 100 | \n logger.js | 100 | 100 | 100 | 100 | \n-----------|---------|----------|---------|---------|-------------------\nTest Suites: 1 passed, 1 total\nTests: 2 passed, 2 total\nSnapshots: 0 total\nTime: 2.73 s, estimated 4 s\nRun Code Online (Sandbox Code Playgroud)\n源代码:https://github.com/mrdulin/jest-v26-codelab/tree/main/examples/52493145
\n小智 -3
把它放在 try catch 中会有所帮助:
const error = new Error('模拟错误');
尝试 {
await Promise.reject(error);
Run Code Online (Sandbox Code Playgroud)
} 捕获(错误){
expect(logger.error).toHaveBeenCalledWith(error);
Run Code Online (Sandbox Code Playgroud)
}