aws-sdk-mock icon indicating copy to clipboard operation
aws-sdk-mock copied to clipboard

Not able to mock AWS.Lamba

Open Sufiane opened this issue 6 years ago • 9 comments

I'm trying to mock a function (invoke) from Lambda but it apperas that when the code is executed the mock does not trigger and it's result in a real call being made. You can find my code below:

awsMock.mock('Lambda', 'invoke', () => {
      return {
        promise: () => {
          return Promise.rejects(/* my error code here*/)
        }
      }
    })

Am I missing something? My aws-sdk-mock is already in the top level node_modules folder.

Thanks in advance for your help ! (any help is welcome!)

Sufiane avatar Sep 10 '18 11:09 Sufiane

I am having the same issue here is a simple test demonstrating the issue:

it('MockAWS.mock should mock Lambda invoke', () => {
            const AWS = require('aws-sdk');
            const MockAWS = require('aws-sdk-mock');
            MockAWS.mock('Lambda', 'invoke', () => 5);

            const lambda = new AWS.Lambda();

            const results = lambda.invoke();
            expect(results).to.be.equal(5);
        });

AssertionError: expected { Object (promise, createReadStream) } to equal 5

============================================================ For those that are stuck here is a work a round

 it('MockAWS.mock should mock Lambda invoke', () => {
            const AWS = require('aws-sdk');
            AWS.Lambda = function() {
                return { invoke: () => 5 };
            };

            const lambda = new AWS.Lambda();

            const results = lambda.invoke();
            expect(results).to.be.equal(5);
        });

pheintzelman avatar Sep 15 '18 00:09 pheintzelman

It works for me as expected. I use typescript so code a little diff

` import * as AWS from 'aws-sdk'; import * as AWSMock from 'aws-sdk-mock'; AWSMock.setSDKInstance(AWS); test.only('AWSMock.mock should mock Lambda invoke', async () => { AWSMock.mock('Lambda', 'invoke', (params, callback) => { callback(null, 5); });

    const lambda = new AWS.Lambda();

    const results = await lambda
        .invoke({
            FunctionName: 'SomeFunction',
            InvocationType: 'RequestResponse',
            LogType: 'Tail',
            Payload: '{ "key" : "value" }'
        })
        .promise();
    expect(results).toEqual(5);

    AWSMock.restore('Lambda');
});

`

jest -c jest.json ./tests/mock.spec.ts ✓ AWSMock.mock should mock Lambda invoke (11ms)

Are you sure you're waiting for the lambda to complete the invocation ?

leriksen avatar Feb 01 '19 04:02 leriksen

@leriksen maybe it's because we (I?) weren't using the callback function. It's kind of old now, I'll have to check if this was the issue.

Anyway thanks for your feedback !

Sufiane avatar Feb 01 '19 09:02 Sufiane

It works for me as expected. I use typescript so code a little diff

` import * as AWS from 'aws-sdk'; import * as AWSMock from 'aws-sdk-mock'; AWSMock.setSDKInstance(AWS); test.only('AWSMock.mock should mock Lambda invoke', async () => { AWSMock.mock('Lambda', 'invoke', (params, callback) => { callback(null, 5); });

    const lambda = new AWS.Lambda();

    const results = await lambda
        .invoke({
            FunctionName: 'SomeFunction',
            InvocationType: 'RequestResponse',
            LogType: 'Tail',
            Payload: '{ "key" : "value" }'
        })
        .promise();
    expect(results).toEqual(5);

    AWSMock.restore('Lambda');
});

`

jest -c jest.json ./tests/mock.spec.ts ✓ AWSMock.mock should mock Lambda invoke (11ms)

Are you sure you're waiting for the lambda to complete the invocation ?

Having the same problem. The test works when the lambda invocation is within the test code. moving it to an async function in another file results in a Async callback was not invoked within the 5000m error. Digging with jest --runInBand show that the mock AWS.Lambda is not used, but tried to initialize the real AWS.Lambda.

mcbain avatar Sep 18 '19 10:09 mcbain

I had the same issue with CloudWatch and when I was mocking it, mock was not working. To fix it, in my function I had to change import * as AWS from 'aws-sdk' to import { CloudWatch } from 'aws-sdk'

zmaleki avatar Jan 06 '20 08:01 zmaleki

Facing the same issue. Mocks for all other services seem to be working fine. @zmaleki Your workaround fix is working for now at least.

jammymalina avatar Feb 06 '20 12:02 jammymalina

It works for me as expected. I use typescript so code a little diff

import * as AWS from 'aws-sdk';
import * as AWSMock from 'aws-sdk-mock';
AWSMock.setSDKInstance(AWS);
test.only('AWSMock.mock should mock Lambda invoke', async () => {
AWSMock.mock('Lambda', 'invoke', (params, callback) => {
callback(null, 5);
});
const lambda = new AWS.Lambda();

const results = await lambda
  .invoke({
    FunctionName: 'SomeFunction',
    InvocationType: 'RequestResponse',
    LogType: 'Tail',
    Payload: '{ "key" : "value" }'
  })
  .promise();
   expect(results).toEqual(5);
  
  AWSMock.restore('Lambda');
  });

Run the test:

 jest -c jest.json ./**tests**/mock.spec.ts
✓ AWSMock.mock should mock Lambda invoke (11ms)

Are you sure you're waiting for the lambda to complete the invocation ?

Having the same problem. The test works when the lambda invocation is within the test code. moving it to an async function in another file results in a Async callback was not invoked within the 5000m error. Digging with jest --runInBand show that the mock AWS.Lambda is not used, but tried to initialize the real AWS.Lambda.

I'm having the same issue as you. Did you find out any workaround for this?

jianlong90 avatar Mar 19 '20 08:03 jianlong90

It works for me as expected. I use typescript so code a little diff ` import * as AWS from 'aws-sdk'; import * as AWSMock from 'aws-sdk-mock'; AWSMock.setSDKInstance(AWS); test.only('AWSMock.mock should mock Lambda invoke', async () => { AWSMock.mock('Lambda', 'invoke', (params, callback) => { callback(null, 5); });

    const lambda = new AWS.Lambda();

    const results = await lambda
        .invoke({
            FunctionName: 'SomeFunction',
            InvocationType: 'RequestResponse',
            LogType: 'Tail',
            Payload: '{ "key" : "value" }'
        })
        .promise();
    expect(results).toEqual(5);

    AWSMock.restore('Lambda');
});

`

jest -c jest.json ./tests/mock.spec.ts ✓ AWSMock.mock should mock Lambda invoke (11ms)

Are you sure you're waiting for the lambda to complete the invocation ?

Having the same problem. The test works when the lambda invocation is within the test code. moving it to an async function in another file results in a Async callback was not invoked within the 5000m error. Digging with jest --runInBand show that the mock AWS.Lambda is not used, but tried to initialize the real AWS.Lambda.

Exactly i'm facing same issue, it works when mocked inside the same test case. Did you find a solution.??

I tried this way too

import * as AWS from 'aws-sdk'

in my actual file. No luck yet.

karthikvadla avatar May 06 '20 15:05 karthikvadla

Got this working this way.

actual file: lambda-sampe.ts

import * as AWS from "aws-sdk";

export const handler = async (event: { ServiceToken: string; LogicalResourceId: string; RequestId: string; ResponseURL: string; ResourceType: string; ResourceProperties: { ServiceToken: string; Configuration: { clientId: string; userPoolId: string }; UniqueKey: string; AliasName: string; LambdaFunction: string }; StackId: string; RequestType: string }) : Promise<string> => {
    const { ResourceProperties } = event;
    const {LambdaFunction, Configuration} = ResourceProperties;


    try {
        console.log(`Adding configuration to Lambda function ${LambdaFunction}:\n${Configuration}`);
        console.log("Configuration: \n", Configuration)
        const LAMBDA_CLIENT = new AWS.Lambda();
        console.log("Client: ", LAMBDA_CLIENT)
        const { Code } = await LAMBDA_CLIENT.getFunction({ FunctionName: LambdaFunction }).promise();
        console.log(Code);
        return "success";
    } catch (err) {
        console.log(err)
        return "error";
    }
}

export function getAWS() {
    return AWS;
}

lamda.test.js

import * as AWSMock from 'aws-sdk-mock'
import * as lambda_sample from "../src/lambda_sample"

it("should mock getFunction from Lambda", async () => {
    AWSMock.setSDKInstance(lambda_sample.getAWS());
    const data = {
        Code: {
            Location: "https://awslambda-us-west-2-tasks.s3.us-west-2.amazonaws.com/snapshots/123456789012/my-function-e7d9d1ed-xmpl-4f79-904a-4b87f2681f30?versionId=sH3TQwBOaUy...",
            RepositoryType: "S3"
        }
    };
    AWSMock.mock('Lambda', 'getFunction', (params: Object, callback: Function) => {
        console.log(params)
        console.log('Lambda', 'getFunction', 'mock called');
        callback(null, data);
    });

    const event = {
        ServiceToken: "arn:aws:lambda:us-east-1:12342316:function:GRIMSBY-sam-lambda-code-update",
        ResponseURL: "pre-signed-url-for-response",
        StackId: "arn:aws:cloudformation:us-east-2:namespace:stack/stack-name/guid",
        RequestId: "unique id for this request",
        LogicalResourceId: "name of resource in template",
        RequestType: "Create",
        ResourceType: "Resource type",
        ResourceProperties: {
            ServiceToken: "arn:aws:lambda:us-east-1:12342316:function:GRIMSBY-sam-lambda-code-update",
            AliasName: "live",
            LambdaFunction: "arn:aws:lambda:us-east-1:12342316:function:GRIMSBY-sam-test",
            UniqueKey: "random_key",
            Configuration: {
                userPoolId: "UserPoolID",
                clientId: "UserPoolClientID",
            }
        }
    };

    const result = await lambda_sample.handler(event)
    console.log(result);
    expect(result).toEqual("success")
    AWSMock.restore('Lambda');
});

karthikvadla avatar May 06 '20 22:05 karthikvadla