Unit testing a Serverless application (part 1)

Pedro Fernando Marquez Soto
A man with no server
5 min readFeb 22, 2017

In almost every software developer job interview I’ve seen, both interviewer and interviewed will tell an awful lie: They love TDD (Test Driven Development) and they never start a project without it. Cut to a few weeks later and they are sweating to increase the coverage percentage in their code to to pass at least the 50% mark.

It’s understandable: Most of the time, we’re hired in projects which already have thousands of lines of code and zero planned hours to improve the unit tests, which often are inadequate in quality and quantity.

However, if we are going to adventure ourselves into the seas of the Serverless architecture without a team of good testers, automated testing is as important as the tested code.

Unit tests are what keep you sane at night when you start messing around the house of cards that is your code, praying that your one fix didn’t cause two new defects.

`https://www.reddit.com/r/Planetside/comments/5r73wy/just_dbg_fixing_bugs/

Every project needs those tests, but when you’re working with something as changing and new as AWS Lambda, automated tests become your notification alerts that let you know something changed, even if you haven’t touched your code.

The cheapest way to develop: TDD

The Serverless Framework offers an invoke command, which allows you to run your Lambda functions, allowing to pass the input data the function rcprvyd. The only condition to this is that you have to deploy your functions to AWS before you try to invoke them.

This means that, every time you need to run one of your functions as you write your code, you need to package your code and upload it to AWS. This will end up in fees for the data upload to S3, and for the execution of all the AWS services you are using in your functions.

How many times do you run your code while you’re developing? Each time it will translate in charges.

That’s why it’s important to follow a TDD approach, using locally run tools. More than getting the known advantages of TDD like avoiding possible defects, in this case you’re literally and immediately saving money.

Since we are using Node.js for our services, let’s leverage existing Node tools.

Mocha and Babel

Any test framework for Node.js is good for our case. I choose Mocha because it’s simple and I’m used to it; but you can use any other tool you feel comfortable with.

Let’s start a new project with the Serverless Framework, configure Mocha to build our tests and Babel to enable the use of ES6 features like Class.

Last year AWS started supporting Node.js 4.3.2, which introduced ES6. However, we need Babel for Mocha to transpile ES6 code for our tests.

I previously mentioned my fondness for tacos, so lets start a small project about a hypothetical application to view and rate tacos:

serverless create — template aws-nodejs — path taco-gallery

Serverless will generate the expected handler.js and serverless.yml files. Let’s install Mocha and Babel, to start building our tests.

Inside the taco-gallery folder, start a Node.js project and install the dependencies running the following commands:

npm init

npm install — save babel babel-core babel-preset-es2015 mocha chai

npm install -g mocha

Also, don’t forget to put the .babelrc file in the root of our project. This will guarantee that when we run our tests, Babel will transpile our code to ES2015 (ES6).

The handler.js file by default has only one function, hello. Testing that function is trivial, but is a good start.

mocha handler.test.js — compilers js:babel-core/register

This looks good for our hello function. Now we can run our function as many times we want without having to package and deploy our application.

However, if we are building our whole application on AWS Lambda functions, this is not a realistic scenario. Our code will be a lot more complex and the test doesn’t even fix our cost issues with other AWS services.

The people at Serverless Framework understand that limitation and they wrote a guide about unit testing. Let’s follow their example and decouple our business logic from the Serverless functions:

If you run the same test, it should pass; but we should change it to test the TacoGallery class directly, so our tests concentrate only in the logic, without having to mock the context objects in each test.

It’s still not really clear of the advantages of this decoupled code, as the function is really simple and we still haven’t addressed the issue of the existing AWS services. Don’t worry, today we just build the base for our project to grow freely.

In our next post we will introduce a DynamoDB database and add more business logic.

--

--