3

I have a nodejs express app using AWS Lambda that writes to, and searches a DynamoDB. I am trying to write integration tests using Jest and @shelf/jest-dynamodb, but having problems clearing and populating the db before each test file runs - it is inconsistent, sometimes all 3 events are populated in time, sometimes only 2, and sometimes none at all. It is important the DB is in an empty state at the start of each test file.

I have a jest.config file:

module.exports = {
  preset: '@shelf/jest-dynamodb',
};

jest-dynamodb-config.js

module.exports = {
  tables: [
    {
      TableName: 'DB',
      KeySchema: [{ AttributeName: 'eventId', KeyType: 'HASH' }],
      AttributeDefinitions: [{ AttributeName: 'eventId', AttributeType: 'S' }],
      ProvisionedThroughput: { ReadCapacityUnits: 1, WriteCapacityUnits: 1 },
    },
  ],
  endpoint: 'http://docker.for.mac.localhost:8000',
};

I have a dbHelper.js

const { DocumentClient } = require('aws-sdk/clients/dynamodb');
const logger = require('../../config/logger-config');

const isTest = process.env.JEST_WORKER_ID;
const config = {
  convertEmptyValues: true,
  ...(isTest && { endpoint: 'localhost:8000', sslEnabled: false, region: 'local-env' }),
};

const ddb = new DocumentClient(config);

const populateDb = async (event) => {
  await ddb.put({ TableName: 'DB', Item: event }, (err, res) => {
    if (err) {
      logger.error(`populateDb ERROR: ${err}`);
    } else {
      logger.info('populateDb OK!');
    }
  });
};

const clearDb = async (event) => {
  await ddb.delete({ TableName: 'DB', Key: { eventId: event.eventId } }, (err, res) => {
    if (err) {
      logger.error(`clearDb ERROR: ${err}`);
    } else {
      logger.info('clearDb OK!');
    }
  });
};

module.exports = {
  populateDb,
  clearDb,
};

And I have 3 test files:

  • one which tests my endpoint can post to dynamoDB
  • one which tests I can search by eventId
  • one which tests I can search by other attributes

For the first test file, I run a beforeAll() which should clear anything that might be in the table:

beforeAll(async () => {
    jest.setTimeout(JEST_TIMEOUT);

    await clearDb(eventA)
    await clearDb(eventB)
    await clearDb(eventC)
  });

// then run tests - only 1 event is actually written so I collect the eventId (as it is created randomly) and clear in afterAll()

afterAll(async () => {
          await clearDb(response.data)
        })

For the 2nd file, I again clear any mock events that may be in there and populate with one event:

beforeAll(async () => {
    jest.setTimeout(JEST_TIMEOUT);

    await clearDb(eventA)
    await clearDb(eventB)
    await clearDb(eventC)

    await populateDb(eventA)
});

// run tests

And in the third file, I again clear all events and populate with 3 events:

beforeAll(async () => {
    jest.setTimeout(JEST_TIMEOUT);

    await clearDb(eventA)
    await clearDb(eventB)
    await clearDb(eventC)

    await populateDb(eventA)
    await populateDb(eventB)
    await populateDb(eventC)
  });

// run tests

I have added callbacks to my dbHelper functions to try and ensure the functions complete before moving on but this doesn't seem to be working.

I have also added the -i flag to my jest run command so all files run sequentially instead of in parallel.

John Rotenstein
  • 241,921
  • 22
  • 380
  • 470
Heather
  • 41
  • 2
  • 5
  • your use of `await` in `clearDb` and `populateDb` is incorrect, hence you are not handling things asynchronously. Since await requires a promise, you would need to `await ddb.put().promise()` – LostJon Oct 18 '19 at 18:34
  • 1
    Thanks for your help. I think that has solved my issue! – Heather Oct 18 '19 at 19:29

0 Answers0