首页 > 解决方案 > AWS Mock 无法模拟 Lambda 调用()

问题描述

我试图在我的 Jest 中模拟一个 Lambda.invoke() 调用。但是,模拟调用不起作用,而是执行了真正的 invoke() 方法,该方法导致not authorized to perform: lambda:InvokeFunction. 我无法找出问题所在,因为我在模拟 DynamoDB.DocumentClient 时也做了同样的事情,而且它没有任何问题。

笑话文件:

describe('Mock Lambda', () => {

    beforeAll(async () => {
        AWSMock.mock('Lambda', 'invoke', (params, callback) => {
            if (params.FunctionName === 'MyLambaInvocation') {
                callback(null, { status: 200, data: { code: '0', message: 'Successful' }
            } 
        });

        const result = await (myTest.handler(event, context(), null) as Promise<APIGatewayProxyResult>);
    });

打字稿文件:

import { Lambda } from 'aws-sdk';

export function invokeLambda(eventObject) {
    return new Promise<any>((resolve, reject) => {
        const lambdaConfig = {
            region: 'ap-southeast-1',
            endpoint: process.env.IS_OFFLINE ? 'http://localhost:8080' : undefined
        };

        const lambda = new Lambda(lambdaConfig);

        const params = {
            FunctionName: 'MyLambaInvocation',
            Payload: JSON.stringify(eventObject)
        };

        lambda.invoke(params, (error, result) => {
            if (error) {
                reject(error);
            } else {
                resolve(result);
            }
        });
    });
}

标签: unit-testingaws-lambdajestjsaws-sdkaws-sdk-mock

解决方案


这是一个仅使用 jestjs 模拟的示例。

index.ts

import { Lambda } from 'aws-sdk';

export function invokeLambda(eventObject) {
  return new Promise<any>((resolve, reject) => {
    const lambdaConfig = {
      region: 'ap-southeast-1',
      endpoint: process.env.IS_OFFLINE ? 'http://localhost:8080' : undefined,
    };

    const lambda = new Lambda(lambdaConfig);

    const params = {
      FunctionName: 'MyLambaInvocation',
      Payload: JSON.stringify(eventObject),
    };

    lambda.invoke(params, (error, result) => {
      if (error) {
        reject(error);
      } else {
        resolve(result);
      }
    });
  });
}

index.test.ts

import { invokeLambda } from './';
import { Lambda as LambdaMock } from 'aws-sdk';

jest.mock('aws-sdk', () => {
  const mLambda = { invoke: jest.fn() };
  return { Lambda: jest.fn(() => mLambda) };
});

describe('Mock Lambda', () => {
  it('should invoke lambda', async () => {
    const mLambda = new LambdaMock();
    const mResult = {};
    (mLambda.invoke as jest.Mocked<any>).mockImplementationOnce((params, callback) => {
      callback(null, mResult);
    });
    const actual = await invokeLambda({});
    expect(actual).toEqual({});
    expect(LambdaMock).toBeCalledWith({ region: 'ap-southeast-1', endpoint: undefined });
    expect(mLambda.invoke).toBeCalledWith(
      {
        FunctionName: 'MyLambaInvocation',
        Payload: JSON.stringify({}),
      },
      expect.any(Function),
    );
  });

  it('should handle error if invoke failure', async () => {
    const mLambda = new LambdaMock();
    const mError = new Error('network');
    (mLambda.invoke as jest.Mocked<any>).mockImplementationOnce((params, callback) => {
      callback(mError);
    });
    await expect(invokeLambda({})).rejects.toThrow('network');
    expect(LambdaMock).toBeCalledWith({ region: 'ap-southeast-1', endpoint: undefined });
    expect(mLambda.invoke).toBeCalledWith(
      {
        FunctionName: 'MyLambaInvocation',
        Payload: JSON.stringify({}),
      },
      expect.any(Function),
    );
  });
});

带有覆盖率报告的单元测试结果:

 PASS  stackoverflow/60753252/index.test.ts
  Mock Lambda
    ✓ should invoke lambda (8ms)
    ✓ should handle error if invoke failure (3ms)

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |     100 |       75 |     100 |     100 |                   
 index.ts |     100 |       75 |     100 |     100 | 7                 
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        4.054s, estimated 11s

源代码:https ://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/stackoverflow/60753252


推荐阅读