I'm having trouble getting the AWS Secrets Manager module mocked for the jest unit tests... The part it errors on is the .promise(). When I remove that, the code doesn't work for the real Secrets Manager so I think it needs to stay there. How do I mock the getSecretData function so that getSecretData.promise() will work for the mock?
Here is the SecretsManager.js code:
import AWS from 'aws-sdk';
export class SecretsManager {
  constructor() {
    AWS.config.update({
      region: 'us-east-1',
    });
    this.secretsManager = new AWS.SecretsManager();
  }
  async getSecretData(secretName) {
    try {
      const response = await this.secretsManager.getSecretValue({
        SecretId: secretName,
      }).promise();
      const secretString = response.SecretString;
      const parsedSecret = JSON.parse(secretString);
      return parsedSecret;
    } catch (e) {
      console.log('Failed to get data from AWS Secrets Manager.');
      console.log(e);
      throw new Error('Unable to retrieve data.');
    }
  }
}
Here is the SecretsManager.test.js code:
import { SecretsManager } from '../utils/SecretsManager';
jest.mock('aws-sdk', () => {
  return {
    config: {
      update(val) {
      },
    },
    SecretsManager: function () {
      return {
        async getSecretValue({
          SecretId: secretName
        }) {
          return {
            promise: function () {
              return {
                 UserName: 'test',
                 Password: 'password',
              };
            }
          };
        }
      };
    }
  }
});
describe('SecretsManager.js', () => {
  describe('Given I have a valid secret name', () => {
    describe('When I send a request for test_creds', () => {
      it('Then the correct data is returned.', async () => {
        const mockReturnValue = {
          UserName: 'test',
          Password: 'password',
        };
        const logger = getLogger();
        const secretManager = new SecretsManager();
        const result = await secretManager.getSecretData('test_creds');
        expect(result).toEqual(mockReturnValue)
      });
    });
    describe('When I send a request without data', () => {
      it('Then an error is thrown.', async () => {
      const secretManager = new SecretsManager();
      await expect(secretManager.getSecretData()).rejects.toThrow();
      });
    });
  });
});
This is the error I get when running the tests:
 this.secretsManager.getSecretValue(...).promise is not a function
Any suggestions or pointers are greatly appreciated!
Thank you for looking at my post.
I finally got it to work... figures it'd happen shortly after posting the question, but instead of deleting the post I'll share how I changed the mock to make it work incase it helps anyone else.
Note: This is just the updated mock, the tests are the same as in the question above.
// I added this because it's closer to how AWS returns data for real.
const mockSecretData = {
  ARN: 'x',
  Name: 'test_creds',
  VersionId: 'x',
  SecretString: '{"UserName":"test","Password":"password"}',
  VersionStages: ['x'],
  CreatedDate: 'x'
}
jest.mock('aws-sdk', () => {
  return {
    config: {
      update(val) {
      },
    },
    SecretsManager: function () {
      return {
        getSecretValue: function ( { SecretId } ) {
          {
           // Adding function above to getSecretValue: is what made the original ".promise() is not a function" error go away.
            if (SecretId === 'test_creds') {
              return {
                promise: function () {
                  return mockSecretData;
                }
              };
            } else {
              throw new Error('mock error');
            }
        }
      }
    };
  }
}});
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With