如何用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属性。 - Mock
transaction时必须执行传入的回调函数,否则内部的fact.findAll不会触发。 - 用
mockResolvedValue模拟异步函数的返回值,确保测试用例能正确等待异步操作完成。
内容的提问来源于stack exchange,提问作者Gigabit
相关产品推荐
相关产品推荐

