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

Express.js应用中使用Jest模拟Axios调用失败,求解决方案

如何在Jest中模拟Express应用的Axios第三方调用

你的测试失败主要源于几个关键问题,下面逐一分析并给出修正方案:

问题分析

  • Axios模拟结构错误:Axios的get方法返回的响应是包含data字段的对象,你直接将用户数据传给mockResolvedValueOnce,导致controller中response.data取不到有效值。
  • 响应数据断言位置错误:supertest返回的接口响应数据存储在res.body属性中,直接断言res.id、res.role会得到undefined。
  • Express响应写法错误:res.send(...).status(200)的链式调用顺序有误,status()需放在send()之前,否则无法正确设置HTTP状态码。
  • 错误处理缺失:controller中未在catch块返回错误响应,会导致测试时请求因未完成而挂起。

修正后的代码

controller.js

const axios = require('axios');

const baseUrl = "Some 3rd party url";

const getUser = async (req, res) => {
    let url = baseUrl + '/user';
    try {
        // 改用async/await让代码更简洁易读
        const response = await axios.get(url);
        // 先设置状态码再发送响应
        res.status(200).send(response.data);
    } catch (error) {
        console.log(error);
        // 添加错误响应,避免请求挂起
        res.status(500).send('Error fetching user');
    }
};

module.exports = {
    getUser
};

test.js

const axios = require('axios');
const supertest = require('supertest');
const app = require('../server');
const request = supertest(app);

jest.mock("axios");
const baseUrl = "Some 3rd party url";

describe("GET /user", () => {
    it("should return a user successfully", async () => {
        // Given
        const mockUser = {
            id: "1234567",
            role: "Test"
        };
        // 模拟Axios真实响应结构:包含data字段
        axios.get.mockResolvedValueOnce({ data: mockUser });

        // When
        const res = await request.get('/user');

        // Then
        expect(axios.get).toHaveBeenCalledWith(`${baseUrl}/user`);
        expect(res.statusCode).toBe(200);
        // 从res.body中获取接口返回的JSON数据
        expect(res.body.id).toBe("1234567");
        expect(res.body.role).toBe("Test");
    });

    it("should return 500 error when fetching user fails", async () => {
        // Given
        axios.get.mockRejectedValueOnce(new Error('Third party API failure'));

        // When
        const res = await request.get('/user');

        // Then
        expect(axios.get).toHaveBeenCalledWith(`${baseUrl}/user`);
        expect(res.statusCode).toBe(500);
        expect(res.text).toBe('Error fetching user');
    });
});

关键修正说明

  1. Axios模拟结构:按照Axios真实响应格式,用{ data: mockData }作为mock返回值,确保controller能正确解析数据。
  2. 响应断言方式:通过res.body访问接口返回的JSON内容,这是supertest获取响应数据的标准方式。
  3. 响应顺序调整:先调用res.status()设置状态码,再调用res.send()发送响应,确保状态码生效。
  4. 完善错误处理:在controller的catch块中添加错误响应,避免测试时请求因未完成而超时。
  5. 补充错误测试:新增失败场景的测试用例,让测试覆盖正常和异常两种情况,保证代码健壮性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 13:52:14