Jest提取mock函数实现灵活mock Sequelize findAll返回值失效问题
问题根因
你的代码有三个明显问题导致mock不生效:
- jest.mock提升机制冲突:
jest.mock会被Jest自动提升到所有代码执行前运行,你在外部定义的mockRecordsFindAll变量在jest.mock执行时还未完成初始化,拿到的值是undefined - findAll赋值语法错误:你写的
findAll: () => mockRecordsFindAll相当于调用records.findAll()时返回的是mock函数本身,而不是执行mock函数得到的结果,和预期逻辑完全不符 - 异步返回与属性匹配错误:Sequelize的
findAll是异步方法返回Promise,你的mock需要返回Promise对象;另外数组长度属性是length不是size,原测试能通过属于巧合
解决方案
有两种常用实现方式都可以满足自定义返回值的需求:
方案1:从mock的initModels中获取findAll引用(更稳妥,无变量提升问题)
const repository = require('../../../src/db/repository/repository'); const initModels = require('../../../src/db/model/init-models'); // 先mock initModels jest.mock('../../../src/db/model/init-models', () => { // 内部定义mock函数 const mockRecordsFindAll = jest.fn(); return function() { return { records: { findAll: mockRecordsFindAll } // 其他模型的mock逻辑补充在这里 } } }); describe('fetchRecords', () => { let mockFindAll; beforeEach(()=> { // 每次测试前获取最新的mock函数实例,重置状态 mockFindAll = initModels().records.findAll; mockFindAll.mockReset(); }); test('should return correct number of records', async () => { // 异步方法用mockResolvedValue设置返回值 mockFindAll.mockResolvedValue([1,2,3]); const result = await repository.fetchRecords(); // 数组长度用length属性 expect(result.length).toStrictEqual(3); }); test('should throw error when query failed', async () => { // 模拟抛出错误场景 mockFindAll.mockRejectedValue(new Error('DB query error')); await expect(repository.fetchRecords()).rejects.toThrow('DB query error'); }); })
方案2:使用符合Jest命名规则的外部mock变量
Jest允许在jest.mock的工厂函数中引用名称以mock开头的变量,这类变量会和jest.mock一起被提升,你原来的写法稍作修改即可生效:
// 变量名必须以mock开头 const mockRecordsFindAll = jest.fn(); jest.mock('../../../src/db/model/init-models', () => { return function() { return { records: { // 直接赋值mock函数,不要套一层箭头函数 findAll: mockRecordsFindAll } } } }); describe('fetchRecords', () => { beforeEach(()=> { mockRecordsFindAll.mockReset() }); test('should return correct number of records', async () => { mockRecordsFindAll.mockResolvedValue([1,2,3]); const result = await repository.fetchRecords(); expect(result.length).toStrictEqual(3); }); })
内容的提问来源于stack exchange,提问作者gzz
相关产品推荐
相关产品推荐

