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.