Easy Testing of Amazon (AWS) Lambda Micro-Services

(See the GitHub repo to clone the code)

AWS Lambda is a service (currently in Preview) that allows us to easily run code in response to certain events. What that means is we can easily create small Micro-Services that do one thing and do it well in response to any given event. Good exmaples include:

Currently Lambda only supports Node.js... Luckily I love Node! They also have a very reasonable free tier so we can try it out.

How to Test Locally?

Since Lambda is a hosted PaaS (Platform as a Service) offering from AWS you get a lot for your money (great for lazy coding) but you also lose some control. Testing is one of those things you lose some control of when it's not easy to remote into the machine.

Lambda Logs in AWS Cloud Watch Example of Lambda logs in AWS Cloud Watch.

Creating a Simple Local Test Harness

Luckily for us, it's easy to create a test harness locally to simulate the Lambda environment events and run our code. This allows us to use our existing debugging toolset, e.g. node inspector, WebStorm, Visual Studio etc.

For example, in this sample, we simulate an S3 file Put event and call our code in the same way Lambda would.

The test.js file:

// Our Lambda function fle is required 
var importify = require('./importify.js');

// The Lambda context "done" function is called when complete with/without error
var context = {
    done: function (err, result) {
        console.log('------------');
        console.log('Context done');
        console.log('   error:', err);
        console.log('   result:', result);
    }
};

// Simulated S3 bucket event
var event = {
    Records: [
        {
            s3: {
                bucket: {
                    name: 'hotlunch-west-2'
                },
                object: {
                    key: 'importing/org_create_table_test/4-25-mytestfile.docx'
                }
            }
        }
    ]
};

// Call the Lambda function
importify.handler(event, context);

The importify stub - your Lambda function entry point:

var AWS = require('aws-sdk');

// Your exported Lambda entry point
exports.handler = function(event, context) {
    console.log('Received event:');
    console.log(JSON.stringify(event, null, '  '));

    // S3 information from the event
    var bucket = event.Records[0].s3.bucket.name;
    var key = event.Records[0].s3.object.key;

    // Do something with the S3 information
    doSomething(bucket, key, function (err, result) {
        console.log('error:', err);
        console.log('result:', result);

        // Notify Lambda done with error or result
        context.done(err, result);
    });
};

Running the Test Locally

Running the test locally is easy, from the command line (or terminal on Mac):

> node test.js

Why this isn't Perfect

Of course what we're doing here isn't perfect - we're not simulating the Lambda environment precisely (including memory limits). But we do now have a way to quickly develop and test Lambda micro-services locally and then deploy them to Lambda for integration testing. This process minimizes the "change-zip-upload-run-check logs" process that is required otherwise.

How to Test Remotely?

I'm working on this one... hopefully I'll have a update soon!

Lambda Limitation in Preview

Since Lambda is in preview, there are some published limitations and also some that we've found out through using it on a daily basis:

Having said this, Lambda is an awesome service that I strongly recommend you try.