Jul*_*dez 7 javascript node.js async-await jestjs
这是我在单元测试时遇到的一个设计问题。\n让我们深入研究示例:
\n想象一下:
\nasync function foo()\xc2\xa0{\n try {\n return apiCall()\n }\n catch (e) {\n throw new CustomError(e);\n } \n}\n\n\n\nasync function bar() {\n return foo()\n}\n\n\n\nasync function main() {\n try {\n await bar()\n }catch(e) {\n console.error(e)\n }\n}\n\nmain()\n
Run Code Online (Sandbox Code Playgroud)\n我们在这里看到什么?唯一没有 try-catch 块的函数是 bar。\n但是如果 foo 失败,它应该被 main catch 捕获。
\n虽然像这样进行单元测试
\ndescribe(\'testing bar\', () => {\n it(\'foo should throw\', () => {\n foo.mockImplementantion(() => { throw new CustomError(\'error\')});\n bar()\n .then((result) => console.log(result))\n .catch((err) => { exepect(err).toBeInstanceOf(CustomError)}) // this is what we are testing\n })\n})\n
Run Code Online (Sandbox Code Playgroud)\n我们看到的输出是控制台中记录了未处理的承诺拒绝。
\n所以,我的问题是......即使我知道会main()
捕获错误,我是否应该在所有异步函数中使用 try-catch 块?
try..catch
如果函数能够从错误中恢复、执行日志记录等副作用或重新抛出更有意义的错误,则可能有必要。
IfCustomError
比可能apiCall
抛出 thentry..catch
必要的错误更可取,否则则不会。还有一个问题foo
是它只处理同步错误。为了处理被拒绝的承诺,应该是这样return await apiCall()
,这是一个已知的陷阱async
。
未捕获的拒绝是不需要的,它们目前会导致UnhandledPromiseRejectionWarning
并且预计会在未来版本中导致 Node 崩溃。最好在顶层以有意义的方式处理错误,因此main
需要捕获错误。这可以委托给process
uncaughtRejection
事件处理程序,但它可能有益于保持不应达到的额外错误处理级别。
我们看到的输出是控制台中记录了未处理的承诺拒绝。
这不应该发生。拒绝需要通过测试来处理。上面解释了一个可能的失败点,foo
可以返回原始错误,apiCall
而不是CustomError
在没有正确模拟的情况下,这将不符合预期并导致catch()
. 另一个失败点是测试有不受约束的承诺,因为它没有返回,测试总是通过。
使用 Promise 的异步测试应该始终返回 Promise。这可以通过使用来改进async..await
。foo
是的async
,它应该总是返回一个承诺:
it('foo should throw', async () => {
foo.mockImplementantion(() => { return Promise.reject(new CustomError('error')) });
await expect(bar()).rejects.toThrow(CustomError);
})
Run Code Online (Sandbox Code Playgroud)
现在,即使foo
模拟失败(如果它们是在所示的同一模块中定义的,则foo
模拟不会影响)并拒绝某些不是的东西,这将被断言。bar
bar
CustomError
归档时间: |
|
查看次数: |
9089 次 |
最近记录: |