首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Jest中,当被测试的函数不使用异步/等待时,我可以使用异步/等待吗?

在Jest中,当被测试的函数不使用异步/等待时,我可以使用异步/等待吗?
EN

Stack Overflow用户
提问于 2022-01-16 22:52:59
回答 1查看 1.2K关注 0票数 0

我有一个简单的控制器来添加新用户。在成功的解析(用户添加)之后,控制器发送202响应。如您所见,该函数使用的是然后/catch,而不是使用异步/等待。

代码语言:javascript
运行
复制
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 ()部分,从而导致错误的200段代码,而不是202段,因此以下测试失败:

代码语言:javascript
运行
复制
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);
});

然而,当我这样做的时候:

代码语言:javascript
运行
复制
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,这意味着函数等待和测试通过。但是为什么呢?当我在新添加的“等待”VS代码上盘旋时,意味着

的“等待”对此表达式的类型没有影响。

这是有意义的--它应该没有任何效果,因为测试的函数不是异步的,所以它不应该工作,但是很好,它可以工作--只有当我向Jest函数添加异步/等待时,它才能正常工作。

有人能给我解释一下吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-01-16 23:06:12

我添加了异步/等待,它工作正常-响应状态代码为202,这意味着函数等待和测试通过。但是为什么呢?

不,正如您从缺少的返回值中得出的结论,函数没有等待。您的代码相当于

代码语言:javascript
运行
复制
apiController.addUserController(req, res, next);
await undefined;

现在,为什么它仍然有影响呢?因为使用await,测试在运行expect()调用之前等待一小段时间,而这个微小位就足以让您的模拟池返回一个值并执行第一个.then()处理程序。

但是,您现在基本上介绍了一个竞赛条件。在addUserController中拥有更长的承诺链将使测试失败。也许对在.then().catch()中创建的500状态的测试可能已经不起作用了。

这是非常脆弱的,不要写这样的测试。一种解决方案是简单地return来自addUserControllerawait的承诺链--只要没有其他调用者对此感到困惑,这就是简单的修复。另一种解决方案实际上是等待实际发送模拟响应。如果我正确地阅读了docs of node-mocks-http,这样的内容应该会奏效:

代码语言:javascript
运行
复制
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);
});
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70734846

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档