簡體   English   中英

承諾在 Jest 測試中沒有正確拒絕

[英]Promise not rejecting correctly in Jest test

當承諾拒絕使用 Jest 時,我正在嘗試測試console.error輸出。 我發現在我的測試運行后,承諾似乎正在解決,導致測試失敗。

示例函數:

export default function doSomething({ getData }) {

  const success = data => {
    //do stuff with the data
  }
  const handleError = () => {
    //handle the error
  }

  getData.then(response => success(response)).catch(error => {
    console.error(error)
    handleError()
  })

}

示例測試文件:

import doSomething from "doSomething"

it("should log console.error if the promise is rejected", async () => {
  const getData = new Promise((resolve, reject) => {
    reject("fail");
  });
  global.console.error = jest.fn();
  await doSomething({ getData });
  expect(global.console.error).toHaveBeenCalledWith("fail");
})
//fails with global.console.error has not been called

當我探索這個問題時,我注意到如果我添加一個 console.log 並等待它,它就可以工作。

這將通過...

import doSomething from "doSomething"

it("should log console.error if the promise is rejected", async () => {
  const getData = new Promise((resolve, reject) => {
    reject("fail");
  });
  global.console.error = jest.fn();
  await doSomething({ getData });
  await console.log("anything here");
  expect(global.console.error).toHaveBeenCalledWith("fail");
})

我如何正確測試? 我應該重構我的getData函數的調用方式嗎? 一旦doSomething函數被調用,它就需要被調用。

為什么原始測試失敗?

理解為什么第一個測試示例不會通過的技巧是深入研究await運算符實際在做什么。 來自Mozilla 文檔

[rv] = await expression;
  • expression - 一個 Promise 或任何要等待的值。
  • rv - 返回 Promise 的已履行值,如果它不是 Promise,則返回值本身。

在您的第一個測試中, expression的值是doSomething函數的返回值。 您不會從此函數返回任何內容,因此返回值將為undefined 這不是一個 Promise,所以await什么都不做,它只會返回undefined並繼續前進。 expect語句將失敗,因為您實際上還沒有等待內部承諾: getData.then(...).catch(...)

要修復測試,而不添加額外的行,請await console.log("anything here"); , 只需從doSomething函數return內部承諾,以便await運算符將實際操作 Promise。

export default function doSomething({ getData }) {
  return getData.then(...).catch(...);
  ...
}

這是測試這個的正確方法嗎?

我不認為doSomething函數的編寫方式有什么大問題。 這種依賴注入通常使函數更容易測試,而不是試圖模擬函數的內部工作。

我只承認,因為您正在注入一個 Promise ( getData ),並在函數內解析它,所以您使doSomething函數異步(這使得測試變得更加復雜)。

如果您解析了 Promise,然后在它解析為的值上調用doSomethinggetData.then(doSomething).catch(handleError) ,您的doSomething函數將是同步的並且更容易測試。 我還要說,以這種方式編寫它會使異步發生的事情變得更加冗長,而原始的doSomething({ getData })將其隱藏在doSomething函數體中。

所以沒有什么是嚴格不正確的,但也許需要考慮的一些事情可能會使測試更容易並且代碼更冗長。 我希望這有幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM