使用Jest和Sequelize进行单元测试:不应通过的测试却成功通过
解决Jest异步测试未执行断言就通过的问题
我来帮你排查这个坑!你遇到的核心问题是异步测试没有被正确等待,导致Jest在断言执行前就直接结束了测试流程——这就是明明断言错得离谱,测试却还显示通过的原因。接下来一步步拆解问题、给出修复方案:
先揪出两个关键问题
1. Controller里的语法错误
先看你的controller.js,try块后面少了一个闭合的},这会导致代码运行报错,不过因为测试没等待异步流程,这个错误也没被暴露出来:
// 修复前的错误部分 async getUserByID(req, res) { try { var user = await userModel.findOne({ where: { id: req.params.id } }); res.status(201).send(user); catch (error) { // 这里缺少try的闭合} res.status(500).send(error) } }
2. 异步测试未被Jest正确等待
你的测试代码里,getUserByID是异步函数,返回Promise,但你没有把这个Promise交给Jest——Jest不知道要等异步操作完成,会直接结束测试,根本没机会执行里面的expect断言:
// 修复前的测试代码 it('should get user from mock', () => { var req = httpMocks.createRequest({ params: { id: 1 } }); var res = httpMocks.createResponse(); controller.getUserByID(req, res).then(function(user) { expect(user.name).toEqual('Steve'); }) // 这里没返回Promise,Jest直接结束测试 });
另外还要注意:你的controller里并没有return用户数据,then的参数里拿不到user,需要用node-mocks-http提供的res._getData()来获取响应内容。
分步修复方案
第一步:修复Controller的语法错误
补全try块的闭合花括号:
const userModel = require('../models').users; module.exports = { async getUserByID(req, res) { try { var user = await userModel.findOne({ where: { id: req.params.id } }); res.status(201).send(user); } // 补上这个闭合花括号 catch (error) { res.status(500).send(error) } } }
第二步:让Jest正确等待异步测试
有两种推荐的写法,选一种就行:
写法一:返回Promise给Jest
把异步操作的Promise返回,Jest会自动等待它完成:
it('should get user from mock', () => { var req = httpMocks.createRequest({ params: { id: 1 } }); var res = httpMocks.createResponse(); // 返回Promise,Jest会等待它resolve/reject return controller.getUserByID(req, res).then(() => { const user = res._getData(); // 获取响应数据 expect(user.name).toEqual('Steve'); }) });
写法二:用async/await(更清晰)
直接用async/await语法,让代码逻辑更直观:
it('should get user from mock', async () => { var req = httpMocks.createRequest({ params: { id: 1 } }); var res = httpMocks.createResponse(); await controller.getUserByID(req, res); // 等待异步操作完成 const user = res._getData(); expect(user.name).toEqual('Steve'); });
验证修复效果
现在运行npm test,你会看到测试正确失败了——因为mock的用户名称是'Tony',而断言是'Steve',这才是符合预期的测试结果。把断言改成expect(user.name).toEqual('Tony'),测试就会正常通过啦。
内容的提问来源于stack exchange,提问作者Dan P
相关产品推荐
相关产品推荐

