4

I have a function that looks like this:

function connect() {
   const secret = 'secret';
   const key = 'key';
   const region = 'region';
   const client = new AWS.DynamoDB({
      secret,
      key,
      region
   });'
   return new AWS.DynamoDB.DocumentClient({ service: client })
}

I would like to test the function connect. I have mocked the DynamoDB constructor like this:

// See https://stackoverflow.com/questions/47606545/mock-a-dependencys-constructor-jest
jest.mock('aws-sdk', () => {
  const DynamoDB = jest.fn().mockImplementation(() => {
    return {};
  });
  return {
    DynamoDB,
  };
});

However, this means that the DocumentClient constructor fails. How do I mock that as well?

skyboyer
  • 15,149
  • 4
  • 41
  • 56
vamsiampolu
  • 5,355
  • 15
  • 65
  • 161

4 Answers4

4

This worked for me:

const mockDynamoDbPut = jest.fn().mockImplementation(() => {
  return {
    promise() {
      return Promise.resolve({});
    }
  };
});

jest.doMock('aws-sdk', () => {
  return {
    DynamoDB: jest.fn(() => ({
      DocumentClient: jest.fn(() => ({
        put: mockDynamoDbPut
      }))
    }))
  };
});

I hope it's helpful for you too.

Regards,

David.

duxtinto
  • 41
  • 1
  • 4
2

DocumentClient might call some of the client method, so simply define those methods stub. Say for example, DocumentClient would use batchGetItem, in your code

import AWS from 'aws-sdk';

jest.mock('aws-sdk', () => {
  const DynamoDB = jest.fn().mockImplementation(() => {
    return {
      batchGetItem: jest.fn(),
    };
  });
  return {
    DynamoDB,
  };
});

// you could inspect the mock
console.log(new AWS.DynamoDB({ ... }));
seanplwong
  • 585
  • 2
  • 11
0

Here what worked for me using jest with TypeScript:

// blabla.test.ts
import { DynamoDB } from 'aws-sdk';
import { ConsumerClass } from '../consumer-class';
import { DependencyConsumerClass } from '../dependency-consumer-class';

/*
* Inside consumerClassInstance.save() is calling this.dynamo.putItem({...}).promise();
*/
jest.mock('aws-sdk', () => {
    return {
        DynamoDB: jest.fn(() => {
            return {
                putItem: jest.fn(() => {
                    return {
                        promise: jest.fn(() => true)
                    };
                })
            };
        })
    };
});

test('sample test', async () => {
    const dependencyConsumerClass = new DependencyConsumerClass();
    const consumerClassInstance = new ConsumerClass(dependencyConsumerClass, new DynamoDB());
    
    const result = await consumerClassInstance.save();
    console.log(result);
});
-1

Jest provides DynamoDB integration for running tests. See this document, look at 3. Configure DynamoDB client:

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

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);

I guess you can abstract out (if you haven't already) the DynamoDB client configuration into its own module file and export that client so that it can be required elsewhere, and when the running Jest tests the client gets configured to point the mock DynamoDB server/tables that you have set up as per the other steps of the Jest DynamoDB documentation.

Jose Quijada
  • 339
  • 1
  • 10
  • It's really good to know that we don't have to write our own helpers to run integration tests (like I've been doing all this time), I would prefer to not use local dynamo server for unit tests. I think we can just use jest.mock('aws-sdk') if using ts-jest because aws-sdk now ships with typescript definitions. – vamsiampolu Jun 16 '20 at 23:08