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

如何用Jest测试含依赖的函数?Mock类型不匹配问题求解

问题描述

需要测试以下函数:

export const Update = (factory: Factory, service: MyService) => {
  return async (input: Input) => {
    return factory.transaction(async (fact) => {
      const someValues = myService.getSomeValues()
      return fact.findAll(someValues, input)
    }
  }
}

测试时尝试传入Mock的Factory类及MyService,但出现类型不匹配错误,测试代码如下:

import Factory from 'factory'
jest.mock('factory')
const mockedFactory = jest.mocked(Factory)
const expectedUpdate = Update(mockedFactory)

错误信息:

Argument of type 'MockedObject' is not assignable to parameter of type 'Factory'. Type 'MockInstance<Factory,
[sequelize: Sequelize]> & {} & { prototype: Factory; }' is missing the
following properties from type 'Factory': sequelize, transaction

需要解决类型错误,同时验证Factory的transaction方法、MyService的getSomeValues方法调用情况,以及fact.findAll的参数和Update函数的返回结果。


解决方案

1. 修正Factory的Mock方式,解决类型不匹配

问题核心是jest.mocked(Factory)拿到的是类的构造函数Mock,而非符合Factory类型的实例对象。需要手动构造或Mock出包含必要属性的实例:

方式一:手动构造符合Factory类型的Mock对象

// 模拟transaction方法,确保执行回调并传入mock的fact对象
const mockTransaction = jest.fn(async (callback) => {
  const mockFact = {
    findAll: jest.fn().mockResolvedValue('mock-result')
  };
  return callback(mockFact);
});

// 构造符合Factory类型的mock对象,用类型断言处理sequelize属性
const mockedFactory: Factory = {
  sequelize: {} as Sequelize,
  transaction: mockTransaction
};

// Mock MyService对象
const myServiceMock = {
  getSomeValues: jest.fn().mockReturnValue('mock-some-values')
};

// 现在传入不会有类型错误
const updateFunction = Update(mockedFactory, myServiceMock);

方式二:Mock可实例化的Factory类

如果Factory是需要实例化的类,直接Mock类的实例方法:

import Factory from 'factory';

jest.mock('factory', () => {
  return jest.fn().mockImplementation(() => {
    return {
      sequelize: {} as Sequelize,
      transaction: jest.fn(async (callback) => {
        const mockFact = { findAll: jest.fn().mockResolvedValue('mock-result') };
        return callback(mockFact);
      })
    };
  });
});

// 创建Mock实例
const mockedFactoryInstance = new Factory();
const myServiceMock = { getSomeValues: jest.fn().mockReturnValue('mock-some-values') };
const updateFunction = Update(mockedFactoryInstance, myServiceMock);

2. 验证函数调用、参数及返回结果

完成Mock后,编写测试用例验证各个环节:

describe('Update function', () => {
  it('should verify all method calls and results', async () => {
    const testInput = { id: 1 };
    
    // 执行Update返回的异步函数
    const result = await updateFunction(testInput);

    // 验证Factory.transaction被调用
    expect(mockedFactory.transaction).toHaveBeenCalledTimes(1);
    
    // 验证MyService.getSomeValues被调用
    expect(myServiceMock.getSomeValues).toHaveBeenCalledTimes(1);
    
    // 获取transaction回调中的mockFact,验证findAll的参数
    const transactionCallback = mockedFactory.transaction.mock.calls[0][0];
    const mockFact = await transactionCallback(jest.fn());
    expect(mockFact.findAll).toHaveBeenCalledWith('mock-some-values', testInput);
    
    // 验证Update函数的返回结果
    expect(result).toBe('mock-result');
  });
});

关键说明

  • 类型错误的本质是传入的Mock对象不符合Factory类型要求,必须包含sequelize和transaction属性。
  • Mocktransaction时必须执行传入的回调函数,否则内部的fact.findAll不会触发。
  • 用mockResolvedValue模拟异步函数的返回值,确保测试用例能正确等待异步操作完成。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 23:05:29