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

使用Jest测试Middy中间件时expect.objectContaining匹配失败

解决Jest测试Middy中间件时expect.objectContaining断言失败的问题

问题场景

测试给AWS Lambda配置的Middy中间件时,该中间件会向request.event添加importantData属性。编写Jest测试用例验证处理器是否收到正确值时,明明参数里包含该属性,但使用expect.objectContaining断言却失败。

相关代码

handler.ts

const main = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
  return {
    statusCode: 200,
    body: `some`
  };
};

export const handler = middy(main)
  .use(myCustomMiddware('somedata'));

myCustomMiddleware.ts

export const myCustomMiddleware = (data: string): middy.MiddlewareObj<APIGatewayProxyEvent, APIGatewayProxyResult> => {
  const before: middy.MiddlewareFn<APIGatewayProxyEvent, APIGatewayProxyResult> = async (request): Promise<void> => {
    Object.assign(request.event, { importantData: 'important' } as { importantData: string });
  };
  return {
    before
  };
};

测试代码(原错误版本)

const mockHandler = jest.fn(async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
  return {
    statusCode: 200,
    body: ''
  };
});

it('event should contain assigned value', async () => {
  const request = {
    event: {
      requestContext: {
        authorizer: {
          claims: {
            'custom:SomeClaimA': 'claimA',
            'custom:SomeClaimB': '1'
          }
        }
      }
    }
  };

  const middleware = middy(mockHandler).use(myCustomMiddleware('somedata'));
  await middleware.before(request as never);

  expect(mockHandler).toHaveBeenCalledWith(expect.objectContaining({ importantData:'important'} ));
});

Jest错误输出

Error: expect(jest.fn()).toHaveBeenCalledWith(...expected)

Expected: ObjectContaining {"importantData": "important"}
Received: {"importantData": "important", "requestContext": {"authorizer": {"claims": {"custom:SomeClaimA": "SomeClaimA", "custom:SomeClaimB": "1"}}}}, {}

原因分析

原测试代码仅调用了middleware.before(request),这只是执行了中间件的before逻辑,修改了request.event,但并没有触发Middy调用mockHandler。mockHandler从未被执行,所以断言toHaveBeenCalledWith必然失败。

解决方案

有两种可行的测试方式:

方案一:直接测试中间件的修改逻辑

直接调用中间件的before函数,验证它是否正确修改了event对象,无需触发完整的handler执行流程:

it('should add importantData to event', async () => {
  const testEvent = {
    requestContext: {
      authorizer: {
        claims: {
          'custom:SomeClaimA': 'claimA',
          'custom:SomeClaimB': '1'
        }
      }
    }
  };

  const middleware = myCustomMiddleware('somedata');
  await middleware.before({ event: testEvent } as never);

  expect(testEvent).toEqual(expect.objectContaining({ importantData: 'important' }));
});

方案二:触发Middy完整执行流程

通过调用Middy包装后的handler,让它执行完整的生命周期(包括中间件和handler),这样就能断言mockHandler的调用参数:

it('handler should receive event with importantData', async () => {
  const testEvent = {
    requestContext: {
      authorizer: {
        claims: {
          'custom:SomeClaimA': 'claimA',
          'custom:SomeClaimB': '1'
        }
      }
    }
  };

  const wrappedHandler = middy(mockHandler).use(myCustomMiddleware('somedata'));
  await wrappedHandler(testEvent as never, {} as never, jest.fn());

  expect(mockHandler).toHaveBeenCalledWith(expect.objectContaining({ importantData: 'important' }), expect.anything(), expect.anything());
});

注意:这里调用wrappedHandler时需要传入三个参数:event、context、callback(可以用jest.fn()模拟),这是Lambda handler的标准签名。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 22:27:22