Express/Node.js Jest测试POST接口返回Response Body为空问题求助
问题根因
你遇到的问题是典型的Jest mock不生效+代码语法缺失导致的,具体有4个明确错误点:
jest.resetModules使用方式错误:你在beforeEach中调用了jest.resetModules()清除模块缓存,但测试文件顶部就提前引入了app和executeDb2Query实例,重置缓存后没有重新引入,导致你写的mock逻辑根本没有被app加载的控制器使用,控制器调用的是未mock的原始方法,自然返回空数据。- 模块引入和mock不匹配:如果你的
../../utils/db2.js是命名导出executeDb2Query(也就是导出代码为module.exports = { executeDb2Query }),那你测试代码里直接const executeDb2Query = require('../../utils/db2.js')拿到的是整个模块对象,不是函数,对这个对象调用mockImplementation完全无效。 - 控制器代码存在语法缺失:你贴的控制器代码中,
await executeDb2Query获取结果后直接写了返回200响应的逻辑,后面却跟着} else {分支,明显缺失了if (getDetails?.length > 0)这类前置判断,实际运行会直接抛出语法错误,就算mock生效也无法正常返回结果。 - 断言结构不匹配:你mock的
executeDb2Query返回的是包含对象的数组,但你贴的测试代码里expect的预期值是单个对象,没有包裹数组,就算数据返回正常也会断言失败。
修复方案
- 调整测试代码的模块引入逻辑,配合
jest.resetModules在每个测试用例执行前重新引入模块,保证mock生效:
'use strict' jest.mock('../../utils/db2.js') const request = require('supertest') describe('service read API test', () => { let executeDb2Query let app // 每次测试前重新引入模块,适配resetModules的逻辑 beforeEach(() => { jest.resetModules() // 命名导出用解构写法,默认导出就去掉大括号 ({ executeDb2Query } = require('../../utils/db2.js')) app = require('../../app') }) it('check Details Good', async () => { executeDb2Query.mockImplementation(() => Promise.resolve([ { dnum: '090703', num: 1, startdate: '2021-06-01', enddate: '2022-05-31', rolecode: 5, fnum: 1.049, lastmodifieddate: '2021-06-02 05:34:04.382279', createtime: '2021-06-01 10:53:24.269686' } ]) ) const res = await request(app) .post('/api/v1/abc/xyz') .send({ id: '090703' }) .expect(200) console.log('Response Body :', JSON.stringify(res.body, null, 2)) // 预期值要和返回的数组结构匹配 expect(res.body).toEqual([ { dnum: '090703', num: 1, startdate: '2021-06-01', enddate: '2022-05-31', rolecode: 5, fnum: 1.049, lastmodifieddate: '2021-06-02 05:34:04.382279', createtime: '2021-06-01 10:53:24.269686' } ]) }) })
- 补全控制器代码里缺失的
if判断逻辑,保证语法正确。 - 确认
db2.js的导出方式,和测试、控制器里的引入方式保持一致。
内容的提问来源于stack exchange,提问作者QuickLearner
相关产品推荐
相关产品推荐

