73

I'm working on a aws serverless project and need to test the lambda functions locally.
I am using serverless invoke local -f {function_name} command to test the API calls that does not request any path or query parameters.
My question is how can I use this command to pass any path or query parameter to the function?

Example serverless description

getFoodDetails:
    handler: handler.getFoodDetails
    events:
      - http:
          method: get
          path: /foods/{food_id}
          cors: true
          request:
            parameters:
              paths:
                food_id: true
Kannaiyan
  • 12,554
  • 3
  • 44
  • 83
Lasitha Yapa
  • 4,309
  • 8
  • 38
  • 57

8 Answers8

104

Data string

As being said you can use the --data option to pass a string data as an event to your function.

serverless invoke local -f {function_name} --data '{ "queryStringParameters": {"id":"P50WXIl6PUlonrSH"}}'

Data file

What you can also do is to pass a --path to a json file with data as the event, and within the "event file" define the data you want.

serverless invoke --function {function_name} --path event_mock.json

You could somehow return the event from a call and save it in a JSON file or grab one from Amazon. They provide some examples: https://docs.aws.amazon.com/lambda/latest/dg/eventsources.html

Keep in mind that if you pass both --path and --data, the data included in the --path file will overwrite the data you passed with the --data flag.

Documentation: https://serverless.com/framework/docs/providers/aws/cli-reference/invoke#invoke-local

maxrodrigo
  • 1,660
  • 2
  • 16
  • 20
  • how can you do this with a file? ex. `serverless invoke local --function requestUploadURL --data 'imagepath?' ` – KD.S.T. Nov 01 '19 at 03:31
  • This answer is incomplete. You spcified how to pass the data to the function, but not how to read it from the `event` object. Depending on how you read data from the `event` object, the way to read it is different. – Bersan Jul 23 '23 at 17:11
19

I've tried the answers with the attribute --data but neither works.
In fact the problem is that the --data will pass a string value to the framework. So if you write in your javascript file:console.log(typeof(event));, you will get String instead of Object. Which means serverless framework doesn't transform the input to a JSON object correctly. That's why you got xx of undefined error.

My solution is to use the -p(or --path) attribute. In your example, follow these steps:

  1. create a .json file at the current location of your console. eg: test.json
  2. in the json file write: {"pathParameters":{"food_id":"100"}}
  3. in the js file, to get the food_id, use event.pathParameters.food_id
  4. run command: sls invoke local -f yourFunction -p test.json
barbsan
  • 3,418
  • 11
  • 21
  • 28
Nechadil
  • 341
  • 3
  • 6
17

Use --data and pass is any format of data you want to send it to the local lambda.

String Data Example:

serverless invoke --function functionName --stage dev --region us-east-1 --data "hello world"

JSON Data Example:

serverless invoke --function functionName --stage dev --region us-east-1 --data '{ "property1": "value"}'

JSON Data from file:

serverless invoke --function functionName --stage dev --region us-east-1 --path lib/data.json

Complete documentation can be accessed from here

Hope it helps.

Kannaiyan
  • 12,554
  • 3
  • 44
  • 83
  • Thanks. I added an example API call, can you please show how to pass the `food_id` to that – Lasitha Yapa Sep 10 '18 at 04:53
  • event.pathParameters.food_id is the format you need to send your data in the json. That is how it is passed from API Gateway to the lambda. – Kannaiyan Sep 10 '18 at 05:00
  • serverless invoke local -f getFoodDetails --data '{"event.pathParameters.food_id":"f00"}' I tried this one, but getting the error 'food_id' of undefined. – Lasitha Yapa Sep 10 '18 at 05:20
  • Looks a the example on nested javascript object. https://hackernoon.com/accessing-nested-objects-in-javascript-f02f1bd6387f – Kannaiyan Sep 10 '18 at 06:16
9

For future reference. Your case would have been solved like this. Just figured it out thanks to Kannaiyans JSON Example.

sls invoke local -f getFoodDetails --data '{ "queryStringParameters": {"food_id":"123"}}'
d0utone
  • 180
  • 11
9

QueryStringParameters and pathParameters are two different input types.

For the former the accepted response works to me.

For the later is pretty much the same, just replace queryStringParameters by pathParameters

sls invoke local -f {function_name} --data '{ "pathParameters": {"id":"1"}}'
pafede2
  • 1,626
  • 4
  • 23
  • 40
2

There is also an alternative to all the other options here. I wrote a blog article about this and will link it after going through some of the detail.

There are two basic aspects you need to handle:

  1. Execute the code in your handler and business logic by passing event objects to your handler
  2. Handling requests to AWS services in a way that makes it easy to test

For the first one, I just added Mocha to the project and used the unit testing framework as a way to be able to click a button in my IDE and have my code be executed with test data. I can also do local debugging, step through code etc without issue. The added advantage is, if you just set this up, like I have, purely to execute your code, you still have the beginnings of a unit test suite you can flesh out later if you wish

For the second one, its even easier. There is an npm module called aws-sdk-mock and it allows you to register a listener for a specific AWS service and method (such as DynamoDB.query or S3.putItem) and respond to that request with whatever you wish, even errors if you wish to test how your code handles the unthinkable; an AWS service going down.

With the setup of these two elements, I can locally test any handler I develop. Ultimately you will always need to do some integration testing in the cloud as there is just no local substitute, no matter how elaborate or awesome it seems, for the actual cloud services you will be using, but this can get you quite far.

https://serverless.com/blog/serverless-local-development

Gareth McCumskey
  • 1,510
  • 7
  • 12
0

One challenge with local invoke that you seem to have run into is debugging the lambda runtime vs the dynamodb resource. Ideally, you want to invoke both the lambda runtime and the live dynamodb table. Today, serverless local invoke and the AWS SAM CLI both invoke the lambda runtime, but not the live cloudstack.

As long as you have your Lambda's ARN, you can invoke both the lambda runtime as well as the cloudstack with the Stackery CLI. (it's free) Here is an example debugging a serverless framework lambda.

Abnerg
  • 41
  • 4
0

By the way, you can create another function and put into it all test cases for the one you wanted to invoke.

module.exports.testerFunction = () => {
  functionIWatnedToInvoke(para1, para2, para3);
  functionIWatnedToInvoke(para4, para5, para6);
  functionIWatnedToInvoke(para7, para8, para9);
}

then

sls invoke local --function testerFunction
Amr
  • 433
  • 5
  • 12
  • You can programmatically create other test cases with loops and unit testing functions too – Amr Jan 03 '22 at 23:27