Mocking AWS DynamoDB

A guide on how to mock AWS DynamoDB ๐Ÿฆ„

Mocking AWS DynamoDB

We all love living in the cloud, right? Yes we do! As long as we have an internet connection and the services in the cloud are available and accessible.

At times we do not want to rely on having access to cloud services. For example when developing locally or when running tests that should only verify the behaviour of our application and not the behaviour of its external dependencies. In this guide I will show you how you can mock the DynamoDB API so that you no longer need access to the internet or AWS itself while developing.

Let's start off with a simple example where we interact with DynamoDB to fetch some data from a table.

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

// Use our mock DynamoDB API instead of AWS
AWS.config.dynamodb = { endpoint: 'http://localhost:3001', region: 'eu-west-1' };

const dynamoDbClient = new AWS.DynamoDB.DocumentClient();

dynamoDbClient.get({TableName: 'TasksTable', Key: 'someTask'})
    .promise()
    .then(result => {
        console.log(result.Item)
    });

Assuming that there is a table called TasksTable with an item that has the key Gardening we should see something like the following print:

{ Type: 'Gardening', Description: 'Mow the lawn', DueDay: 'Saturday' }

Now we want to create a mock version of DynamoDB that we can use locally.

To do this we will use Mocki that will help mock the API. Install the tool in your project to get started:

npm install mocki --save-dev

Next up we will create a configuration file that we will call dynamo-mock.yml. This will define the mocked DynamoDB service and its responses. Use the below configuration or set up your own by referencing the documentation.

name: dynamodb-mock
port: 3001
endpoints:
  - path: /
    method: post
    behavior: conditional
    responses:
      - statusCode: 200
        condition:
          operator: eq
          comparand: headers.x-amz-target
          value: DynamoDB_20120810.GetItem
        body:
          Item:
            Type:
              S: Gardening
            Description:
              S: Mow the lawn
            DueDay:
              S: Saturday
        headers:
          - name: content-type
            value: application/json

This will return the object that we expect to get from Dynamo.

Run your mock by running the following command in your project directory: npx mocki run --path dynamo-mock.yml.

When that is running we can change our code to point to the mock instead of AWS service by modifying our code like this:

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

// Use our mock DynamoDB API instead of AWS
AWS.config.dynamodb = { endpoint: 'http://localhost:3001', region: 'eu-west-1' };

const dynamoDbClient = new AWS.DynamoDB.DocumentClient();

dynamoDbClient.get({TableName: 'TasksTable', Key: 'Gardening'})
    .promise()
    .then(result => {
        console.log(result.Item)
    });

This will point the AWS SDK to our mock instead and run the requests to that instead of the real DynamoDB service.

Let's try it out by running the code and you should get the same result as when we started out. However this time we are not interacting with AWS at all, everything is happening locally and without HTTP calls over the internet. Pretty cool, huh?

It is possible to use the same approach for mocking out all of the AWS services. Under the hood they are all just regular APIs accessed with HTTP requests. In coming articles I will guide you through mocking many more of AWS and other cloud services using mock HTTP servers. Stay tuned!