【问题标题】:Testing a promise that's expected to fail using Jest使用 Jest 测试预期会失败的 Promise
【发布时间】:2021-09-15 16:48:21
【问题描述】:

我正在尝试使用 Jest 来测试一个返回承诺的函数。

函数 manyUrls 需要传递一个包含 JSON 数据的 URL 数组。获取这些 URL 的内容并以数组的形式返回。 我正在测试传递有效 URL 字符串的情况。这会按预期抛出 TypeError,但我无法使用 Promise 为其编写测试(async/await 工作正常)

//index.js
const manyUrls = (urls) => {
  return Promise.all(urls.map(url => fetch(url)))
    .then(responses =>
      Promise.all(responses.map(res => res.json()))
    ).then(texts => {
      return Promise.resolve(texts)
    }).catch(error => {
      return Promise.reject(error)
    })
} 

//index.test.js
const manyUrls = require("./index")
const url = 'https://jsonplaceholder.typicode.com/todos/1'


test('Expect TypeError if a single string is passed', () => {
  // expect.assertions(1);
  // try {
  //   await manyUrls(url);
  // } catch (e) {
  //   expect(e).toBeInstanceOf(TypeError);
  // }


  return manyUrls(url).catch(e =>
    expect(e).toBeInstanceOf(TypeError)
  )
})

我已经注释掉了使用 async/await 成功通过该测试用例的部分代码(如果我将异步添加到回调中),但我正在尝试使用 Promise 来完成这项工作。我已按照https://jestjs.io/docs/asynchronous 上的文档进行操作,但似乎无法通过该测试。有谁知道为什么?

提前致谢,

【问题讨论】:

  • 不要包含文字图片。使用普通代码标记显示该文本。至于您的代码:如果urls 可以为空,请使用if (!urls) { return Promise.reject(new Error(...)); } ... 更新您的函数,因为您的代码应该能够处理它。有测试来验证代码是否有效,尤其是在遇到极端情况时。你找到了一个边缘案例。所以先修复你的代码。
  • 我还添加了文字。我知道我的功能可能包括输入检查,但我的问题是关于测试承诺。如您所见,抛出了一个 TypeError 并且我的测试需要一个 TypeError 实例,但测试用例仍然失败......
  • 作为 Stackoverflow 的新用户:请像其他人一样关注the posting guidelines。您的图像是文本的图像,而是显示该文本,标记为代码。并且绝对在这里形成一个minimal reproducible example,主要是为了强迫自己找到真正的问题(然后,一旦你将事情减少到最低限度并且你仍然有这个问题,那个代码让其他人帮助您更好地解决问题)。
  • 我删除了图片并重新提出了我的问题。如果还不行,请告诉我。
  • 现在记得将 error 也显示为普通文本。我的 cmets 不是关于“删除图像”,而是关于 not using images when you're showing text:复制粘贴实际文本,并将其放入代码块中,使其成为等宽格式。另请注意,您的代码不是可运行的 sn-p,它是节点/笑话代码,因此不要将其放在可运行标签中,只需使用常规代码格式即可。

标签: javascript asynchronous testing jestjs


【解决方案1】:

如果您的 manyUrls 函数返回一个 Promise,您的 return manyUrls(url)... 代码将正常工作 - 但当 urls 参数不是数组时,它不会

返回 Promise 并以 Error 拒绝的函数与抛出 Error 的函数之间存在很大差异。通过在您的测试中使用return,您是在告诉 Jest 您的函数是前者,而实际上您的函数是后者。

manyUrls 的第一行,return Promise.all(urls.map(url => fetch(url))) 尝试调用urls.maps,但当urls 不是数组时抛出错误(如在测试用例中)。在抛出错误时,不会返回任何 Promise。

您的 try/catch 实现有效,因为它捕获了 manyUrls 抛出的错误。如果您希望 return 实现工作,那么 manyUrls 必须返回一个拒绝的 Promise。

manyUrls 更新为总是 返回 Promise 的最简单方法是添加 async 关键字 - 就像在 const manyUrls = async (urls) => { 中一样。通过使其成为异步函数,manyUrls 抛出的任何错误都将自动转换为返回的 Promise 的拒绝值。见:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function#return_value

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-27
    • 1970-01-01
    • 1970-01-01
    • 2020-04-21
    • 1970-01-01
    • 2018-03-24
    • 2013-01-30
    • 1970-01-01
    相关资源
    最近更新 更多