簡體   English   中英

當測試的 function 沒有使用 async/await 時,我可以在 Jest 中使用 async/await 嗎?

[英]Can I use async/await in Jest, when the tested function is not using async/await?

我有一個簡單的 controller 用於添加新用戶。 解析成功后(用戶添加),controller發送202響應。 如您所見,function 使用的是 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 中測試這個 function 時,function 立即執行,而不轉到 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);
});

那就是我添加了異步/等待,它工作正常 - 響應狀態代碼是 202,這意味着等待 function 並且測試通過。 但為什么? 當我 hover 超過新添加的 'await' VS 代碼提示

'await' 對這個表達式的類型沒有影響。

嗯,這是有道理的 - 它應該沒有效果,因為經過測試的 function 不是異步的,所以它不應該工作,但是它可以工作 - 只有當我將 async/await 添加到 Jest function 時它才能正常工作。

有人可以向我解釋一下嗎?

我添加了 async/await,它工作正常 - 響應狀態代碼為 202,這意味着等待 function 並且測試通過。 但為什么?

不,正如您從缺少的返回值中得出的結論,不等待 function。 您的代碼相當於

apiController.addUserController(req, res, next);
await undefined;

現在,為什么它仍然有所作為? 因為使用await ,測試在運行expect()調用之前會等待一小段時間,而這一小段位足以讓您的模擬池返回一個值並執行第一個.then()處理程序。

但是,您現在基本上引入了競爭條件。 在 addUserController 中有更長的addUserController鏈會使測試失敗。 甚至對.then().catch()中創建的 500 狀態的測試可能已經無法正常工作。

這很脆弱,不要寫這樣的測試。 一種解決方案是簡單地從addUserController return promise 鏈並await它 - 只要沒有其他調用者對此感到困惑,這是簡單的修復。 另一種解決方案是實際等待模擬響應實際發送。 如果我正確閱讀了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);
});

暫無
暫無

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

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