'Using different jest mocks of a class for separate unit tests

I am working with AWS and writing some unit tests for a class that makes use of AWS's Secrets Manger service. For those interested, I'll link the documentation to Secrets Manager here: https://docs.aws.amazon.com/secretsmanager/index.html

On to the question: I am trying to write two unit tests for a class that uses Secrets Manager, specifically the 'getSecretValue' function. The gist of my code is below:

Consumer Function File: secretValueManager.ts

import { SecretsManager } from 'aws-sdk';

const manager = new SecretsManager({});

export default async function retrieveSecretValue(secretId: string) { 
 try { 
   const result = await manager.getSecretValue({ secretId });
   return {
      value: result.SecretString,
    };
 } catch (err: any) {
    throw new Error('encountered an error retrieving secret');
 }
};

Spec/Test file: secretValueManager.spec.ts

import retrieveSecretValue from './secretValueManager';

// MOCK #1
jest.mock('aws-sdk', () => {
  return {
    __esModule: true,
    SecretsManager: function (): any {
      return {
        getSecretValue: function (): any {
          return {
            promise: jest.fn().mockImplementation(() => ({
              SecretString: 'returned signingKey',
            })),
          };
        },
      };
    },
  };
});

// MOCK #2
jest.mock('aws-sdk', () => {
  return {
    __esModule: true,
    SecretsManager: function (): any {
      return {
        getSecretValue: function (): any {
          return {
            promise: jest.fn().mockImplementation(() => {
              throw new Error('error_message');
            }),
          };
        },
      };
    },
  };
});

describe('secretsManager', () => {

  it('should get secret value', async () => {
    await expect(retrieveSecretValue('secretid')).resolves.toBe({ value: 'returned signingKey' });

  });

  it('should re-throw error with custom message', async () => {
    await expect(retrieveSecretValue('secret id')).rejects.toThrow('encountered an error retrieving secret');
  });

});

As you can see, mock #1 is meant to test the 'try' block with the first individual test, and mock #2 is meant to test the 'catch' block with the second individual test. Obviously, I can't call jest.mock() twice and change the mock on a per test basis.

What I am used to doing is importing functions on their own and making use of the jest function mockImplementationOnce(), but the 'getSecretValue' function is not an exported function and only exists on instances of the 'SecretsManager' class.

I know that mock #1 results in test 1 passing, and that mock #2 results in test 2 passing, but how can I use both of these mocks on a per test basis?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source