英文:
Jest expect.objectContaining fails even if expected object is part of received
问题
// in my .test.ts file
describe('test', () => {
  const mockHandler = jest.fn(async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
    return {
      statusCode: 200,
      body: ''
    };
  });
  it('event should contain assigned value', () => {
    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' }));
  });
});
英文:
I want to test my middy middleware for my lambda handler using jest. In the middleware I assign a propperty to the request.event which then will be used in the handler.
//hander.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> => {
    // Do stuff
    Object.assign(request.event, { importantData: 'important' } as { importantData: string });
  };
};
return {
  before
};
Now I want to write a test if the handler receives the correct value:
// in my .test.ts file
describe('test', () => {
  const mockHandler = jest.fn(async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
    return {
      statusCode: 200,
      body: ''
    };
  });
  it('event should contain assigned value', () => {
    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'} ));
  });
But for some reason jest tells me that the importantData is not part of the received parameter when it actually is. This is the output I get from the jest runner:
Error: expect(jest.fn()).toHaveBeenCalledWith(...expected)
Expected: ObjectContaining {"importantData": "important"}
Received: {"importantData": "important", "requestContext": {"authorizer": {"claims": {"custom:SomeClaimA": "SomeClaimA", "custom:SomeClaimB": "1"}}}}, {}
答案1
得分: 1
所以这是因为显然 middy 在底层调用基本处理程序,它接收两个参数 await baseHandler(request.event, request.context);
一个提示应该是测试运行程序的输出末尾的 {}。
所以更新后的匹配器应该像这样:
expect(mockHandler)
    .toHaveBeenCalledWith(expect.objectContaining({ 
        importantData: 'important' }), expect.anything());
这会引发一个断言,所以你必须在测试开始时添加 expect.assertions(1)。
我不完全明白为什么会发生断言,但我认为 .toHaveBeenCalledWith 会引发一个,因为我们没有一个精确的匹配。
英文:
So the reason for this is that apparently middy calls the base handler under the hood which receives two arguments await baseHandler(request.event, request.context);
A hint should've been the {} at the end of the Received output of the testrunner.
So the updated matcher should look like this:
    expect(mockHandler)
    .toHaveBeenCalledWith(expect.objectContaining({ 
     importantData:'important'} ), expect.anything());
This raises an assertion so you have to add expect.assertions(1) at the start of the test.
I not completely understand why an assertion is happening, but I assume that .toHaveBeenCalledWith raises one since we do not have an exact match?
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论