You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Supertest测试报404错误排查(Postman请求正常)

问题:Supertest调用接口返回404,但Postman请求正常

我正在为基于Express、Sequelize的PostgreSQL数据插入接口编写单元测试,使用Supertest调用/calculation接口时,测试抛出「expected 200 OK, got 404 Not Found」错误,但Postman请求该接口可正常返回200结果。以下是相关代码,请问问题出在哪里?

测试代码

const app = require('../../index')
const supertest = require('supertest')
const request = supertest(app)

it('Positive flow', (done) => {
        let reqObj = {
            "name": "Qwerty",
            "class": 2
        }

        let resObj = {
            "success": "yes",
            "message": "done"
        }
  
        const response = request.post('/calculation')
            .send(reqObj)
            .expect(200)
            .end((err, res) => {
                if (err) return done(err)
                response.expect(200)
                response.expect(expect.objectContaining(resObj))
                return done()
        })
})

index.js

const express = require('express');
const router = require('./router')
const PORT = 7000 
const app = express();
app.use(express.json());
app.use('/', router);

module.exports = app;
app.listen(PORT, () => console.log(`PORT:${PORT}`));

router.js

const express = require('express')
const router = express.Router()
const func = require('./calculation')
router.post('/calculation', func.calc)
module.exports = router

calculation业务代码

const models = require('../models')
const calc = async (req, res) => {
    try {
        const calculation = await models.USER_LICENSE.create({
            name: req.name,
            class: req.class,
        });
        return res.status(200).json({"success": "yes", "message":"done"})
    } catch (error) {
        return res.status(400).json({"success": "no", "message":"fail"})
    }
}

问题原因及解决方案

1. 路由匹配失败(404)的核心原因

  • app实例导入路径错误:检查测试文件中require('../../index')的相对路径是否正确。如果测试文件的目录层级与index.js不匹配,会导致导入的不是正确的Express app实例,自然无法匹配路由。
    • 解决:确认测试文件与项目根目录index.js的相对位置,调整导入路径至正确值。
  • 请求路径不匹配:若你实际接口路径是/post/calculation(如问题描述中提到的),但测试代码中请求的是/calculation,会直接导致404。
    • 解决:确认接口实际路径,将测试中的请求路径改为对应值,或检查router的挂载逻辑是否正确。

2. 测试代码的语法错误

  • 错误的断言对象:end回调中使用response.expect(200)是错误的,response是未完成的请求对象,应使用回调参数里的res(响应对象)进行断言。
  • 断言方法使用错误:expect.objectContaining需要通过测试框架(如Jest)的expect调用,且应断言res.body而非请求对象。

修正后的测试代码:

const app = require('../../index')
const supertest = require('supertest')
const request = supertest(app)

it('Positive flow', (done) => {
    const reqObj = {
        "name": "Qwerty",
        "class": 2
    }

    const resObj = {
        "success": "yes",
        "message": "done"
    }

    request.post('/calculation')
        .send(reqObj)
        .expect(200)
        .end((err, res) => {
            if (err) return done(err)
            expect(res.body).toEqual(expect.objectContaining(resObj))
            done()
        })
})

3. 业务代码的潜在问题(虽未导致404,但会引发插入失败)

calculation.js中直接使用req.name和req.class获取参数,但通过express.json()解析的请求体数据存储在req.body中,这样写会导致Sequelize因缺少必填参数抛出错误,返回400状态码。

修正后的calculation代码:

const models = require('../models')
const calc = async (req, res) => {
    try {
        const calculation = await models.USER_LICENSE.create({
            name: req.body.name,
            class: req.body.class,
        });
        return res.status(200).json({"success": "yes", "message":"done"})
    } catch (error) {
        console.error(error)
        return res.status(400).json({"success": "no", "message":"fail"})
    }
}

module.exports = { calc }

4. 优化建议

将index.js中的服务启动逻辑改为条件判断,避免测试时自动启动服务:

if (require.main === module) {
    app.listen(PORT, () => console.log(`PORT:${PORT}`));
}

内容的提问来源于stack exchange,提问作者Renee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 00:42:15