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

Jest单元测试mock SQSService返回undefined解决方法

Jest单元测试mock SQSService方法返回undefined问题修复

环境信息

  • 测试框架:Jest ^26.4.2
  • mock工具:jest-mock-extended ^2.0.6
  • 问题现象:测试文件内直接调用mock的getSqsQueueUrl方法可正常返回预设值,被测系统内部调用该方法时返回undefined,代码可正常编译。

现有代码

测试文件代码

jest.mock('aws-sdk');
jest.mock('../../../lambda-resources/AWS/Services/SQSService');
import { SQS, Request, Service, AWSError } from 'aws-sdk';
import { mockDeep, DeepMockProxy } from 'jest-mock-extended';
import { GetQueueUrlResult } from 'aws-sdk/clients/sqs';
import { SQSService } from '../../../lambda-resources/AWS/Services/SQSService';

let sqsMocked: DeepMockProxy<SQS>;
let sqsServiceMocked: DeepMockProxy<SQSService>;

beforeEach(async () => {
    sqsMocked = mockDeep<SQS>();
    sqsServiceMocked = mockDeep<SQSService>();

    sqsMocked.getQueueUrl.mockReturnValue(new Request<GetQueueUrlResult, AWSError>(new Service(), 'test'));
    sqsServiceMocked.getSqsQueueUrl.mockResolvedValue(Promise.resolve('test'));
})

test('getSqsQueueUrl should...', async () => {
    // 测试文件内直接调用可正常返回预设值,被测系统内部调用时返回undefined
    expect(await sqsServiceMocked.getSqsQueueUrl('a')).toBe('test');          
    await (await LeadsCreator({}, {}))
    // ...其余测试逻辑
})

被测业务代码

const AWSSqs = new AWS.SQS();
const _SqsService = new SQSService(AWSSqs);  

const response = await _SqsService.getSqsQueueUrl("x");
// 此处response实际取值为undefined

根因分析

jest.mock('SQSService对应路径')会自动mock整个SQSService类,但beforeEach中手动通过mockDeep创建的sqsServiceMocked是独立的mock实例,未被Jest注入到被测代码的模块依赖体系中。被测代码执行new SQSService()时拿到的是Jest自动生成的默认mock实例,而非手动配置了返回值的sqsServiceMocked。默认mock的异步方法无预设返回值时会返回undefined,因此出现测试文件内直接调用mock正常、业务代码内调用返回空的现象。

不需要额外将sqsMocked注入sqsServiceMocked,核心是让被测代码实例化SQSService时,拿到的是配置了mock规则的实例。

修复方案

改造beforeEach逻辑,将手动创建的mock实例绑定到Jest自动生成的类mock上,无需修改业务代码:

beforeEach(() => {
    // 清空之前用例的mock状态,避免用例间污染
    jest.clearAllMocks();
    sqsMocked = mockDeep<SQS>();
    sqsServiceMocked = mockDeep<SQSService>();

    // *关键步骤*:配置new SQSService()时返回我们自定义规则的mock实例
    const MockedSQSService = SQSService as jest.Mock;
    MockedSQSService.mockReturnValue(sqsServiceMocked);

    // 配置mock返回值,mockResolvedValue本身会包装Promise,无需额外套Promise.resolve
    sqsMocked.getQueueUrl.mockReturnValue(new Request<GetQueueUrlResult, AWSError>(new Service(), 'test'));
    sqsServiceMocked.getSqsQueueUrl.mockResolvedValue('test');
})

注意事项

  • 所有jest.mock语句必须写在import语句最顶部,因为被测代码中new AWS.SQS()、new SQSService()是模块加载时就执行的顶层代码,import后再调用mock会出现mock不生效问题。
  • 如果业务代码后续需要用到SQS实例的其他方法,可通过MockedSQSService的mock.calls拿到实例化时传入的sqs参数,校验传入实例是否符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 22:09:19