当我尝试在异步函数上使用 toThrow() 时,Jest Test 会记录错误(但仍然通过测试)

Dan*_*ura 3 asynchronous node.js async-await jestjs

我正在尝试使用 Jest 来测试异步函数。到目前为止,我有三个测试似乎正在通过。

\n

但是,测试完成运行后,我收到错误UnhandledPromiseRejectionWarning: Error: expect(received).toThrow(expected)...(请参阅下面的完整日志)。我已经尝试了此处和其他地方(例如GitHub上的这个位置)发布的多种解决方案,但我无法消除该错误。

\n

我有以下异步函数:

\n
async function aliasIsAdmin(alias, roles = DEFAULT_ROLES) {\n  try {\n    const url = "https://xxxxxx.execute-api.us-west-2.amazonaws.com/local/xxxxx/";\n    if (typeof alias !== "string") {\n      throw new Error(\'Entity "alias" must be a string.\');\n    }\n\n    if(!Array.isArray(roles)){\n      throw new Error(\'Entity "roles" must be an array but got "\' + typeof roles + \'". Permission Denied.\');\n    } \n    else if(roles.some((role) => typeof role !== "string")){\n      throw \'Entity "roles" must be an array of strings but got at least one element of type: "\' + typeof alias + \'". Permission Denied.\';\n    }\n\n    let { data } = (await axios.get(url + alias)); //Fetch roles that the alias holds.\n    return data.some((role) => roles.includes(role)); //If alias has any of the roles in the policy, grant access.\n\n  } catch (error) {\n    console.error("Error when attempting to authorize user @" + alias\n      + ". Access for this user has been denied, please try again.\\nError:\\n" + error);\n    return false;\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我写了以下测试:

\n
const { aliasIsAdmin, getRolesByAlias } = require("../authorization");\n\ndescribe(\'aliasIsAdmin\', () => {\n    it(\'should return true\', () => {\n        expect.assertions(1);\n        return aliasIsAdmin("anAdmin")\n        .then((r => {expect(r).toBe(true)}));\n      });\n    \n    it(\'should return false\', () => {\n    expect.assertions(1);\n    return aliasIsAdmin("notAnAdmin")\n    .then((r => {expect(r).toBe(false)}));\n    });\n\n    it(\'should throw\', () => {\n        aliasIsAdmin(1)\n        .then((r => {expect(r).toThrow(\'Entity "alias" must be a string.\')}));\n        });\n});\n
Run Code Online (Sandbox Code Playgroud)\n

当我运行测试时,我得到:

\n
(node:94497) UnhandledPromiseRejectionWarning: Error: expect(received).toThrow(expected)\n\nMatcher error: received value must be a function\n\nReceived has type:  boolean\nReceived has value: false\n(node:94497) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)\n(node:94497) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.\nPASS  public/utils/test/authorization.test.js\n  aliasIsAdmin\n    \xe2\x9c\x93 should return true (895 ms)\n    \xe2\x9c\x93 should return false (238 ms)\n    \xe2\x9c\x93 should throw (37 ms)\n\n  console.error\n    Error when attempting to authorize user @1. Access for this user has been denied, please try again.\n    Error:\n    Error: Entity "alias" must be a string.\n\n      41 | \n      42 |   } catch (error) {\n    > 43 |     console.error("Error when attempting to authorize user @" + alias\n         |             ^\n      44 |       + ". Access for this user has been denied, please try again.\\nError:\\n" + error);\n      45 |     return false;\n      46 |   }\n\n      at aliasIsAdmin (public/utils/authorization.js:43:13)\n      at Object.<anonymous> (public/utils/test/authorization.test.js:17:9)\nTest Suites: 1 passed, 1 total\nTests:       3 passed, 3 total\nSnapshots:   0 total\n
Run Code Online (Sandbox Code Playgroud)\n

我的测试命令是:jest --coverage public/utils/test

\n

eol*_*eol 6

正如错误消息所示,toThrow需要一个函数作为其接收到的值,在您的情况下,它是一个承诺解析的布尔值,因为您捕获了中的所有错误aliasIsAdmincatch 块中的所有错误并 return false

如果您更改 catch 块中的逻辑并重新抛出错误,则可以在单元测试中使用以下内容:

it('should throw', async () => {
      await expect(aliasIsAdmin(1)).rejects.toThrow('Entity "alias" must be a string.');
});
Run Code Online (Sandbox Code Playgroud)

如果当前逻辑是正确的并且您实际上并不希望抛出错误,则需要更改单元测试以检查已解析的false布尔值:

it('should return false if non-string parameter is passed', async () => {
      const result = await aliasIsAdmin(1);
      expect(result).toBe(false);
});
Run Code Online (Sandbox Code Playgroud)