我有一个简单的控制器来添加新用户。在成功的解析(用户添加)之后,控制器发送202响应。如您所见,该函数使用的是然后/catch,而不是使用异步/等待。
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段,因此以下测试失败:
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,这意味着函数等待和测试通过。但是为什么呢?当我在新添加的“等待”VS代码上盘旋时,意味着
的“等待”对此表达式的类型没有影响。
这是有意义的--它应该没有任何效果,因为测试的函数不是异步的,所以它不应该工作,但是很好,它可以工作--只有当我向Jest函数添加异步/等待时,它才能正常工作。
有人能给我解释一下吗?
发布于 2022-01-16 23:06:12
我添加了异步/等待,它工作正常-响应状态代码为202,这意味着函数等待和测试通过。但是为什么呢?
不,正如您从缺少的返回值中得出的结论,函数没有等待。您的代码相当于
apiController.addUserController(req, res, next);
await undefined;
现在,为什么它仍然有影响呢?因为使用await
,测试在运行expect()
调用之前等待一小段时间,而这个微小位就足以让您的模拟池返回一个值并执行第一个.then()
处理程序。
但是,您现在基本上介绍了一个竞赛条件。在addUserController
中拥有更长的承诺链将使测试失败。也许对在.then().catch()
中创建的500状态的测试可能已经不起作用了。
这是非常脆弱的,不要写这样的测试。一种解决方案是简单地return
来自addUserController
和await
的承诺链--只要没有其他调用者对此感到困惑,这就是简单的修复。另一种解决方案实际上是等待实际发送模拟响应。如果我正确地阅读了docs of 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://stackoverflow.com/questions/70734846
复制相似问题