Node.js路由Mock函数问题:无法Mock类方法返回结果
解决Node.js路由测试中Mock类字段箭头函数的问题
我来帮你排查下Mock失败的核心问题,然后给出可行的解决方案:
问题根源分析
你现在的Mock失效主要有两个关键原因:
- 类A的
myFunc是类字段箭头函数,而非原型方法
你用myFunc = async () => {...}这种类字段语法定义的函数,是直接挂载到每个实例对象上的,并不会出现在A.prototype上。所以测试里修改A.prototype.myFunc完全不会影响new A()创建的实例。 - Jest Mock的路径或方式有误
首先要确保jest.mock('A')的路径和你控制器中引入A的路径一致,比如A的文件是../A.js,就得写成jest.mock('../A'),否则Jest找不到要Mock的模块。
方案一:不修改类A代码,Mock实例方法
我们可以让Jest直接Mock类的构造逻辑,让它返回带有Mock版myFunc的实例:
const request = require("supertest"); const app = require("../C"); // 注意路径要和控制器中引入A的路径一致 const A = require("../A"); // Mock整个A类,指定构造时返回的实例内容 jest.mock("../A", () => { return jest.fn().mockImplementation(() => { return { // 直接Mock实例上的myFunc,用mockResolvedValue处理异步返回 myFunc: jest.fn().mockResolvedValue("Mocked Success Result") }; }); }); test("Test route /", async () => { const res = await request(app).get("/"); expect(res.status).toBe(200); expect(res.body).toEqual({ message: "Mocked Success Result" }); // 验证类被实例化、方法被调用 expect(A).toHaveBeenCalled(); expect(A.mock.instances[0].myFunc).toHaveBeenCalled(); });
方案二:修改类A代码(更推荐),改为原型方法
如果可以调整类A的写法,把箭头函数改成普通原型方法,Mock会更符合常规测试逻辑:
修改后的类A代码:
class A { async myFunc() { await ... return result } }
对应的测试文件:
const request = require("supertest"); const app = require("../C"); const A = require("../A"); jest.mock("../A"); test("Test route /", async () => { // Mock原型上的myFunc方法 const mockMyFunc = jest.fn().mockResolvedValue("Mocked Result"); A.prototype.myFunc = mockMyFunc; const res = await request(app).get("/"); expect(res.status).toBe(200); expect(res.body).toEqual({ message: "Mocked Result" }); expect(mockMyFunc).toHaveBeenCalled(); });
额外优化建议
你控制器里的错误处理有个小问题:catch(e => { return [] }),这里如果myFunc抛出错误,你只是返回了空数组,但没有给客户端发送响应,会导致请求挂起、测试超时。建议改成async/await写法并返回错误响应:
router.get("/", async (req, res) => { const a = new A(); try { const result = await a.myFunc(); res.json({ "message": result }); } catch(e) { res.status(500).json({ error: e.message }); } });
内容的提问来源于stack exchange,提问作者Iqbal
相关产品推荐
相关产品推荐

