如何修复「Unhandled rejection TypeError: res.status is not a function」错误?
问题分析与解决方案
你在Express中搭建了目标管理的API端点,在浏览器和Postman里测试都能正常运行,但编写Mocha/Chai测试时却接连遇到错误:先是Unhandled rejection TypeError: res.status is not a function,移除status调用后又出现res.json is not a function,甚至新建基础路由测试还碰到Uncaught TypeError: Cannot read property 'apply' of undefined,最终你找到了问题的根源,这里给你梳理完整的逻辑和修复细节:
问题核心原因
你的路由是Express Router实例,并且已经挂载到了顶层的App路由上(比如你可能在主文件里写了app.use('/api/goals', goalRouter)),但测试时你直接导入了单个的Router实例,而非完整的Express App对象。这导致测试工具(supertest)无法正确模拟完整的Express请求/响应周期,自然找不到res.status、res.json这些内置方法。
相关代码回顾
你的端点代码(Router实例)
router.get('/', (req, res) => { Goal.getAll().then((goals) => { res.status(200).json(goals); }); });
最初的错误测试代码
describe('API routes', () => { beforeEach(() => knex.migrate.rollback() .then(() => knex.migrate.latest()) .then(() => knex.seed.run())); afterEach(() => knex.migrate.rollback()); describe('GET /goals', () => { it('should return all goals set', (done) => { request(route) // 此处导入的是单个Router实例,而非完整App .get('/') .expect(200) .expect((res) => { expect(res.body[0]).toInclude({ title: 'blah blah blah', description: 'blah blah blah', }); }) .end(done); }); }); });
修复步骤及代码示例
- 替换测试的导入对象:停止导入单个Router实例,改为导入你的顶层Express App(比如
app.js或server.js中导出的app对象)。 - 使用完整的端点路径:因为Router挂载在
/api/goals下,测试时要请求完整路径/api/goals而非/。
修复后的测试代码
const app = require('../app'); // 导入顶层Express App对象 describe('API routes', () => { beforeEach(() => knex.migrate.rollback() .then(() => knex.migrate.latest()) .then(() => knex.seed.run())); afterEach(() => knex.migrate.rollback()); describe('GET /api/goals', () => { it('should return all goals set', (done) => { request(app) // 使用完整的App对象发起测试请求 .get('/api/goals') // 请求实际的完整端点路径 .expect(200) .expect((res) => { expect(res.body[0]).toInclude({ title: 'blah blah blah', description: 'blah blah blah', }); }) .end(done); }); }); });
额外补充说明
- Supertest依赖完整的Express App来构建模拟的HTTP请求链路,单个Router实例没有绑定Express的核心中间件和请求处理逻辑,所以无法提供
res.status这类内置方法。 - 保持测试中的端点路径和实际运行环境的路径一致,能避免很多路由匹配类的隐性问题。
内容的提问来源于stack exchange,提问作者Yinka
相关产品推荐
相关产品推荐

