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

Jest+Supertest测试CreateVendor:跨文件Mock函数失败及404错误

问题解决方案

你当前面临两个核心问题:测试返回404错误、无法正确Mock generateSalt/hashPassword函数,以下是针对性的解决步骤:


一、解决404 Not Found错误

404的核心原因是请求路径不匹配或测试用app实例未正确挂载路由:

  • 先确认实际业务中CreateVendor控制器的路由是否确实是POST /admin/vendor,检查路由注册代码是否给控制器加了/admin前缀
  • 验证测试中导入的app实例是否完成了所有路由初始化,比如是否在测试前执行了路由挂载逻辑
  • 临时在测试中添加await supertest(app).get('/')验证基础响应,排查app实例是否正常工作

另外注意:你测试中Mock了Vendor.find,但控制器实际调用的是findVendor('', email),这个自定义函数如果未被Mock,可能导致逻辑异常,但404优先排查路由问题。


二、正确Mock generateSalt和hashPassword

"Property generateSalt does not exist in the provided object"报错,是因为jest.spyOn仅能Mock对象上的方法,而generateSalt是独立导出的函数,必须用jest.mockMock整个模块:

假设你的工具函数模块utilities.ts导出方式如下:

export const generateSalt = async () => { /* 原逻辑 */ };
export const hashPassword = async (pwd: string, salt: string) => { /* 原逻辑 */ };

修正后的Mock写法

// 在测试文件顶部或describe块内,Mock整个工具模块
jest.mock('../../utilities', () => ({
  generateSalt: jest.fn().mockResolvedValue('mocked-salt-123'),
  hashPassword: jest.fn().mockResolvedValue('mocked-hashed-password')
}));

// 导入需要验证的mock函数
import { generateSalt, hashPassword } from '../../utilities';

三、完整修正后的测试用例

import request from 'supertest';
import { app } from '../../app';
import { Vendor } from '../../models/Vendor';
import { findVendor } from '../../services/vendorService'; // 假设findVendor在此模块
import { generateSalt, hashPassword } from '../../utilities';

jest.mock('../../utilities', () => ({
  generateSalt: jest.fn().mockResolvedValue('test-salt'),
  hashPassword: jest.fn().mockResolvedValue('test-hashed-pwd')
}));

describe('CreateVendor function', () => {
  it('creates a new vendor successfully', async () => {
    const mockVendorData = {
      name: 'Test Vendor',
      email: 'test@vendor.com',
      password: 'test123',
      address: 'Test Address',
      foodType: ['Fast Food'],
      ownerName: 'Test Owner',
      phone: '1234567890',
      pincode: '123456'
    };

    // 关键:Mock控制器实际调用的findVendor函数,而非Vendor.find
    jest.spyOn(await import('../../services/vendorService'), 'findVendor').mockResolvedValueOnce(null);
    jest.spyOn(Vendor, 'create').mockResolvedValueOnce(mockVendorData);

    const res = await request(app)
      .post('/admin/vendor')
      .send(mockVendorData)
      .expect(201);

    // 验证响应数据
    expect(res.body.success.name).toBe(mockVendorData.name);
    expect(res.body.success.email).toBe(mockVendorData.email);

    // 验证mock函数调用情况
    expect(generateSalt).toHaveBeenCalledTimes(1);
    expect(hashPassword).toHaveBeenCalledWith(mockVendorData.password, 'test-salt');
    expect(findVendor).toHaveBeenCalledWith('', mockVendorData.email);
  });
});

关键检查点

  1. 路由匹配:确保POST /admin/vendor是控制器的正确注册路径,测试用app已挂载该路由
  2. Mock目标准确:控制器调用的是findVendor,必须Mock这个自定义函数,而非Vendor.find
  3. 独立函数Mock方式:对于独立导出的工具函数,必须用jest.mockMock整个模块,不能用jest.spyOn

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 23:05:18