A guide to mocking overloaded signatures in Jest with TypeScript

I'm currently attempting to create a mock function for a singleton class that retrieves a value from the AWS SSM parameter store.

The type definitions for getParameter() are provided below:

  getParameter(params: SSM.Types.GetParameterRequest, callback?: (err: AWSError, data: SSM.Types.GetParameterResult) => void): Request<SSM.Types.GetParameterResult, AWSError>;
  
  getParameter(callback?: (err: AWSError, data: SSM.Types.GetParameterResult) => void): Request<SSM.Types.GetParameterResult, AWSError>;

This is how my test setup looks:

import {SSM} from 'aws-sdk';
import {SSMParameter} from './src/module/ssm/ssm-cache-parameter';
import {mocked} from 'jest-mock';
import { AWSError } from 'aws-sdk';

jest.mock('aws-sdk', () => {
  const mSSMInstance = {
    getParameter: jest.fn(),
  };
  const mSSM = jest.fn(() => mSSMInstance);

  return { SSM: mSSM };
});


describe('mocking amazon service response', () => {
  let ssmParameter: SSMParameter;
  it('should fetch Parameter from Parameter Store', async () => {
    ssmParameter = SSMParameter.getInstance();
    expect(SSM).toBeCalled();
    console.log(ssmParameter);
    const mSSMInstance = new SSM();
    const mData = {
      Parameter: {
        ARN: 'arn:aws:ssm:eu-test-1:123:NAME',
        LastModifiedDate: new Date(2020, 09, 1),
        Name: 'NAME',
        Type: 'String',
        Value: 'VALUE',
        Version: 1,
      }
    };
    const error: AWSError = {
        code: 'ERROR_CODE',
        message: 'ERROR_MESSAGE',
        name: 'ERROR_NAME',
        time: new Date(2020, 09, 1),
    }
    mocked(mSSMInstance.getParameter).mockImplementationOnce(
      (params: SSM.GetParameterRequest, callback?: (err: AWSError, data: SSM.GetParameterResult) => void): any => {
        if (callback) {
          callback(error, mData);
        }
      },
    );
    const actual = ssmParameter.cache({Name: 'NAME', WithDecryption: false}, 30000);
    expect(actual).toBe('VALUE'); 
  });
});

The error I am encountering seems to be due to TypeScript's uncertainty about which definition to utilize:

Argument of type '(params: SSM.GetParameterRequest, callback?: ((err: AWSError, data: GetParameterResult) => void) | undefined) => any' is not assignable to parameter of type '{ (params: GetParameterRequest, callback?: ((err: AWSError, data: GetParameterResult) => void) | undefined): Request<GetParameterResult, AWSError>; (callback?: ((err: AWSError, data: GetParameterResult) => void) | undefined): Request<...>; }'. Types of parameters 'params' and 'callback' are incompatible. Type '((err: AWSError, data: GetParameterResult) => void) | undefined' is not assignable to type 'GetParameterRequest'. Type 'undefined' is not assignable to type 'GetParameterRequest'.

I've hit a roadblock. Any assistance on how to resolve this issue would be greatly appreciated.

Answer №1

To address the issue, I decided to simulate the signature that was needed for my testing purposes. Here is how I managed to tackle it:

import {SSM, AWSError, Request} from 'aws-sdk';
import {cache} from './src/module/ssm/ssm-cache-parameter-wrapper';

jest.mock('aws-sdk', () => {
  const mRequestInstance = {
    promise: jest.fn(),
  };
  const mRequest = jest.fn(() => mRequestInstance);
  const mSSMInstance = {
    getParameter: jest.fn(() => Request),
  };
  const mSSM = jest.fn(() => mSSMInstance);

  return {Request: mRequest, SSM: mSSM};
});
type GetParameter = (
  params: SSM.Types.GetParameterRequest,
  callback?: (err: AWSError, data: SSM.Types.GetParameterResult) => void
) => any;

describe('AWS System Manager Cache Mock', () => {
  it('should retrieve Parameter from Parameter Store', async () => {
    const mSSMInstance = new SSM();
    const mRequestInstance = new Request(mSSMInstance, 'getParameter', {Name: 'NAME', WithDecryption: false});

    jest
      .mocked(mSSMInstance.getParameter as GetParameter)
      .mockImplementationOnce(
        (
          _params: SSM.Types.GetParameterRequest,
          _callback?: (err: AWSError, data: SSM.Types.GetParameterResult) => void
        ) => mRequestInstance
      );
    jest.mocked(mRequestInstance.promise as any).mockResolvedValueOnce({
      Parameter: {
        Value: 'VALUE',
      },
    });
    const actual = await cache({
      cacheTimeInMilliSeconds: 30000,
      decrypt: false,
      name: 'NAME',
    });
    expect(SSM).toBeCalled();
    expect(Request).toBeCalled();
    expect(actual).toBe('VALUE');
  });
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Promise from Jest not resolving

While testing my express server in Jest, I encountered an issue where all tests pass but Jest doesn't close or exit after completion. It seems like my server is closing after the test runs. To troubleshoot, I ran yarn jest --detectOpenHandles and rece ...

A guide on incorporating Google authentication into Vue.js with the use of TypeScript and the component-based syntax

Currently, I am in the process of integrating Google authentication into my Vue.js front end. The project was initialized using CLI with TypeScript and component style syntax enabled, alongside other configurations. Additionally, there is a backend web ser ...

Angular 11.0.3 displaying ngClass issue (Unable to bind ngClass as it is not recognized as a property of div)

While working on an angular project, I implemented a light and dark theme using mat-slide-toggle to switch between themes. The theme is stored as a boolean called isDark in a Behavioral Subject service. There are two lazy-loaded modules - one for the home ...

The issue with calling a public method from an onchange event triggered by a custom Google Maps control in the Ionic framework has been encountered

Hello, fellow developers! I am relatively new to Ionic and web programming in general. Currently, I am working on a small app that involves integrating the Google Maps JS API. While I have successfully created and loaded the map, as well as added a custom ...

Error: The Class object cannot be found in Object(...)(...)

I've been encountering a TypeError while trying to implement this angular code. The error seems to be generated around Class({constructor: function() {}}), but I'm not exactly sure why. Any help on this would be greatly appreciated. import "hell ...

Using dangerouslySetInnerHTML in ReactJS can potentially strip away data attributes

After adding a data-test attribute to the a anchor tag within an HTML string and inserting it using dangerouslySetInnerHTML, I noticed that the data attributes are somehow being stripped out. Is there a way to prevent this from happening? These attribute ...

No output when using Typescript 2.0

Recently, I've been working on a project in VS 2015 update 3 and just integrated Typescript 2.0. Initially, I encountered a lot of errors and had to go through a trial and error process to resolve them. Now, all the errors have been fixed but I' ...

What steps can be taken to eliminate redundancy in this code and improve its efficiency?

Here I have two methods, create and update, that send data to an API. I am looking to enhance the createUser and updateUser methods as they are very similar. Additionally, if you have any suggestions on a better way to directly set the id property as null ...

Checking for duplicates in a TypeScript array of objects

I am facing a requirement where I must check for duplicates among object items. Within the following Array of objects, I need to specifically look for duplicates in either the "empno" or "extension" properties. If any duplicates are found, an error should ...

How should an error be properly typed in react-query?

I am looking for a way to create a custom error with the appropriate type for react-query's useQuery hook. The goal of this custom error is to include the status code of the response in case of failure, so I can decide whether or not to utilize the us ...

Using a modulus operator in Angular 6 to conditionally show elements

Trying to achieve a specific layout for an object in an array using ng-For and ng-If. Here is the desired recovery code, and here's what I've attempted so far in my code snippet enter image description here: <div class="recovery-code" *ngFor= ...

Exploring Typescript code through a practical example with reference to Uniswap's implementation

On the Uniswap website, I came across some code on the Swap page that caught my attention. You can find the code snippet in question at line 115 of the Uniswap GitHub repository. const { trade: { state: tradeState, trade }, allowedSlippage, cur ...

Tips for referencing functions in TypeScript code

In regard to the function getCards, how can a type be declared for the input of memoize? The input is a reference to a function. import memoize from "fast-memoize"; function getCards<T>( filterBy: string, CardsList: T[] = CardsJSON.map((item, i ...

I require a duplicate of the original data. Direct references are unnecessary

I am trying to extract the value of data.notes. After implementing the code below, I noticed that the detailsOfCurrentNotes value changes based on the data.notes. Can anyone provide guidance on how to resolve this issue? notes :Note[] const detailsOfCur ...

TypeScript: empty JSON response

I am encountering an issue with the JSON data being blank in the code below. The class is defined as follows: export class Account { public amount: string; public name: string; constructor(amount: string, name: string) { this.amount = amount; t ...

The potential issue of undefined objects in TypeScript when utilizing computed properties in Vue3

https://i.sstatic.net/I5ZVO.png I've attempted adding a ? after each word and also experimented with the following code: const totalNameLenght = computed(() => { if (userFirstnameLenght.value && userLastnameLenght.value){ ret ...

Error message: Unable to instantiate cp in Angular 17 application while building with npm run in docker container

After creating a Dockerfile to containerize my application, I encountered an issue. When I set ng serve as the entrypoint in the Dockerfile, everything works fine. However, the problem arises when I try to execute npm run build. Below is the content of my ...

Maintain Angular Dropdown Menu Open Across Page Refresh

I am currently working on an HTML/Typescript view that is connected to a SQL Database. Whenever there are changes made to the database, the entire webpage reloads. The issue we are facing is that we have dropdown menus on the page that clients want to rema ...

Click on the button to generate a PDF report using Internet Explorer 11

After encountering some challenges with printing a PDF report specifically on IE 11, I am reaching out for help. The code snippet below works perfectly in Chrome, but when it comes to IE 11, everything falls apart. Just to provide some context, I am develo ...

predicting the types of arguments by analyzing the context and previous examples

Is there a way to derive the type of one set of arguments from another set in TypeScript? Check out the example below type FormValues = { name: string; height: number; birthDate: Date; } const [value, setValue] = useState<Partial<FormValues&g ...