【问题标题】:Getting the right stack trace out of jest从玩笑中获取正确的堆栈跟踪
【发布时间】:2021-09-28 03:18:42
【问题描述】:

我目前正在调试一些用 jest over typescript 编写的测试,我有点头疼。

如果一个测试或测试类运行 Postgres SQL 并且查询中有错误,我会得到错误的堆栈跟踪,例如:

error: invalid input syntax for type integer: ""0""
    at Parser.parseErrorMessage (/Users/sklivvz/src/xxx/node_modules/pg-protocol/src/parser.ts:369:69)
    at Parser.handlePacket (/Users/sklivvz/src/xxx/node_modules/pg-protocol/src/parser.ts:188:21)
    at Parser.parse (/Users/sklivvz/src/xxx/node_modules/pg-protocol/src/parser.ts:103:30)
    at Socket.<anonymous> (/Users/sklivvz/src/xxx/node_modules/pg-protocol/src/index.ts:7:48)
    at Socket.emit (node:events:365:28)
    at addChunk (node:internal/streams/readable:314:12)
    at readableAddChunk (node:internal/streams/readable:289:9)
    at Socket.Readable.push (node:internal/streams/readable:228:10)
    at TCP.onStreamRead (node:internal/stream_base_commons:190:23)

“错误”行非常有用,但是,堆栈跟踪只告诉我错误是由 pg-protocol 驱动程序引发的。我想知道我的代码中的哪一行产生了错误。

我有 82.7% 的把握确定这是因为 PG 的 query 是异步的。

不得不逐步调试或(喘气)console.log 处理每个错误非常耗时,而这只是显示正确的调用堆栈以使其变得更好的问题。

有没有人找到让这个开发者友好的方法?

【问题讨论】:

  • 您是否允许更新实现而不是开玩笑测试?比如 postgres.query().catch(error =>)。
  • 堆栈跟踪发生这种情况不是因为 Jest,而是因为 Postgres lib 的回调。该错误是在包pg-protocol 内的某处创建的,这也是在您的回调之前。要对代码进行堆栈跟踪,您必须捕获并抛出自己的错误。

标签: javascript typescript postgresql jestjs stack-trace


【解决方案1】:

检查这是否与brianc/node-postgres issue 2484有关

当您从解析器返回语法错误时,是否有首选的包、扩展或方法提供更多详细信息?
(例如,列出行号、错误列)

例如,现在:

error: syntax error at or near "as"
   at Parser.parseErrorMessage (/home/collspec/projects/staff-portal/sprint-server/node_modules/pg-protocol/dist/parser.js:278:15)

期望的行为:

error: syntax error at or near "as", line 5, column 7
   at Parser.parseErrorMessage (/home/collspec/projects/staff-portal/sprint-server/node_modules/pg-protocol/dist/parser.js:278:15)

Possible workaround 来自该问题:

驱动程序填充的错误对象上有许多附加字段。
如果您记录错误对象,您可以看到它们。它们对应于error fields returned by the server

例如使用命令:

SELECT foo
FROM bar

你会得到这样的错误:

{
 length: 102,
 severity: 'ERROR',
 code: '42P01',
 detail: undefined,
 hint: undefined,
 position: '17',
 internalPosition: undefined,
 internalQuery: undefined,
 where: undefined,
 schema: undefined,
 table: undefined,
 column: undefined,
 dataType: undefined,
 constraint: undefined,
 file: 'parse_relation.c',
 line: '1180',
 routine: 'parserOpenTable'
}

你想要的是位置。它为您提供错误 SQL 中的字符偏移量。
在此示例中,位置值“17”指的是 SQL 中柱形标记的开始。
它并不总是被填充,因为它取决于导致错误的原因(通常只是解析错误)。

【讨论】:

  • 谢谢 - 问题不在于 SQL 中语法错误位置的准确性,而在于开玩笑吃掉了 脚本本身所在的位置。如果您有数百个 SQL 脚本并且错误是“SELECT 附近的错误”,那么它不是很有用:-D
  • @Sklivvz 好的,太糟糕了。我试图对抗你昨天提到的风滚草效应 (twitter.com/sklivvz/status/1417761292627152900)
  • 谢谢,我非常感谢您的努力!
【解决方案2】:

我在使用 DynamoDb 的 aws-sdk 时遇到了类似的问题。这是我通常从 aws-sdk 获得的堆栈跟踪。

ResourceNotFoundException: Requested resource not found
at Request.extractError (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\protocol\json.js:52:27)
at Request.callListeners (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\sequential_executor.js:106:20)
at Request.emit (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\sequential_executor.js:78:10)
at Request.emit (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\request.js:688:14)
at Request.transition (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\request.js:22:10)
at AcceptorStateMachine.runTo (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\state_machine.js:14:12)
at D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\state_machine.js:26:10
at Request.<anonymous> (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\request.js:38:9)
at Request.<anonymous> (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\request.js:690:12)
at Request.callListeners (D:\workspaces\typescript-starters\console-app\node_modules\aws-sdk\lib\sequential_executor.js:116:18)

我的解决方法是简单地捕获异步错误,并覆盖它们的堆栈跟踪。另一方面,您可以将 Postgres 堆栈跟踪或错误消息附加到您自己的错误中。

  async function getPersonFromDb (personId: string): Promise<DocumentClient.AttributeMap | undefined> {
    const result = await documentClient.get({ // Similar to postgres.query()
      TableName: 'wrong-name',
      Key: { pk: personId, sk: personId }
    }).promise().catch(error => {
      Error.captureStackTrace(error)
      throw error
    })
    return result.Item
  }

  test('Get a person from DynamoDB', async () => {
    const person = await getPersonFromDb('hello')
    expect(person).not.toBeUndefined()
  })


// ========= new stacktrace ========
Error: Requested resource not found
    at D:\workspaces\typescript-starters\console-app\test\abc.test.ts:12:13
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
    at getPersonFromDb (D:\workspaces\typescript-starters\console-app\test\abc.test.ts:8:20) 
    at Object.<anonymous> (D:\workspaces\typescript-starters\console-app\test\abc.test.ts:18:20) // my code, and where my error is thrown

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-10
    • 1970-01-01
    相关资源
    最近更新 更多