我有一個簡單的控制器來添加新用戶。決議成功(用戶添加)后,控制器發送 202 回應。如您所見,該函式使用的是 then/catch,而不是使用 async/await。
const addUserController = function (req, res, next) {
Users.addOne(req.userid, req.body.email)
.then(() => {
res.status(202).send();
})
.catch((err) => {
console.log(err);
res.status(500).json({ message: "Internal server error." });
});
};
當我在 Jest 中使用 the 測驗這個函式時,該函式立即執行,而不去 then() 部分,導致錯誤的 200 代碼,而不是 202,因此以下測驗失敗:
it("Should add a user", () => {
let req, res, next, pool;
pool = new Pool();
req = httpsMocks.createRequest();
res = httpsMocks.createResponse();
res.next = null;
req.userid = 1;
req.body = {
id: 2
}
pool.query.mockResolvedValue({rows:[], rowCount: 1});
apiController.addUserController(req, res, next);
expect(res.statusCode).toBe(202);
expect(pool.query).toBeCalledTimes(1);
});
但是,當我這樣做時:
it("Should add a user", async () => {
let req, res, next, pool;
pool = new Pool();
req = httpsMocks.createRequest();
res = httpsMocks.createResponse();
res.next = null;
req.userid = 1;
req.body = {
id: 2
}
pool.query.mockResolvedValue({rows:[], rowCount: 1});
await apiController.addUserController(req, res, next);
expect(res.statusCode).toBe(202);
expect(pool.query).toBeCalledTimes(1);
});
那就是我添加了 async/await,它作業正常 - 回應狀態代碼是 202,這意味著該函式已等待并且測驗通過。但為什么?當我將滑鼠懸停在新添加的“等待”VS 代碼上時,提示
'await' 對這個運算式的型別沒有影響。
嗯,這是有道理的——它應該沒有效果,因為測驗的函式不是異步的,所以它不應該作業,但是,它可以作業——只有當我將 async/await 添加到 Jest 函式時它才能正常作業。
有人可以向我解釋一下嗎?
uj5u.com熱心網友回復:
我添加了 async/await,它作業正常 - 回應狀態代碼為 202,表示該函式已等待并且測驗通過。但為什么?
不,正如您從缺少的回傳值中得出的結論,不等待該函式。您的代碼相當于
apiController.addUserController(req, res, next);
await undefined;
現在,為什么它仍然有所作為?因為使用await,測驗在運行呼叫之前會等待一小段時間expect(),而那一小段時間足以讓您的模擬池回傳一個值并.then()執行第一個處理程式。
但是,您現在基本上引入了競爭條件。在 中擁有更長的承諾鏈addUserController會使測驗失敗。甚至對正在創建的 500 狀態的測驗.then().catch()可能已經無法正常作業。
這很脆弱,不要寫這樣的測驗。一種解決方案是簡單return的承諾鏈 from addUserControllerand awaitit - 只要沒有其他呼叫者對此感到困惑,這是簡單的解決方法。另一種解決方案是實際等待模擬回應實際發送。如果我閱讀了正確的檔案node-mocks-http,這樣的東西應該可以作業:
it("Should add a user", async () => {
const { once, EventEmitter } = require('events');
const pool = new Pool();
const req = httpsMocks.createRequest();
const res = httpsMocks.createResponse({ eventEmitter: EventEmitter });
res.next = null;
req.userid = 1;
req.body = {
id: 2
}
pool.query.mockResolvedValue({rows:[], rowCount: 1});
const responseEndPromise = once(res, 'end');
apiController.addUserController(req, res, next);
await responseEndPromise;
expect(res.statusCode).toBe(202);
expect(pool.query).toBeCalledTimes(1);
});
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/416391.html
標籤:
