[英]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,然后在它解析為的值上調用doSomething
, getData.then(doSomething).catch(handleError)
,您的doSomething
函數將是同步的並且更容易測試。 我還要說,以這種方式編寫它會使異步發生的事情變得更加冗長,而原始的doSomething({ getData })
將其隱藏在doSomething
函數體中。
所以沒有什么是嚴格不正確的,但也許需要考慮的一些事情可能會使測試更容易並且代碼更冗長。 我希望這有幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.