Mastering the art of mocking modules with both a constructor and a function using Jest

I'm a Jest newbie and I've hit a roadblock trying to mock a module that includes both a Class ("Client") and a function ("getCreds"). The Class Client has a method called Login. Here's the code snippet I want to test:

import * as sm from 'some-client';
const smCli: sm.Client = new sm.Client();

export const getKey = async (): void => {
    const smCreds = await sm.getCreds();
    await smCli.login(smCreds);
};

The issue I'm facing is that while I can mock the getCreds function easily, I'm not sure how to mock the login function of the Client instance in order to properly test the getKey function. I've tried different approaches like the one below, but none seem to work. Can anyone point out where I'm going wrong? Thank you.

import * as sm from 'some-client';
jest.mock('some-client');

const smClientMock = sm.Client as jest.Mock<unknown>
const smGetCredsMock = sm.getCreds as jest.Mock<Promise<unknown>>

smGetCredsMock.mockResolvedValue(1);
smClientMock.mockImplementation(() => {
    return {
        login: () => {
            return 2;
        }
    };
});

Answer №1

To access the mocked instance of the sm.Client class, you can utilize mockFn.mock.instances. This allows you to make assertions on the .login() method of that particular instance.

For example:

some-client.ts:

export class Client {
  async login(creds) {}
}

export const getCreds = async () => ({ pwd: 'real pwd' });

index.ts:

import * as sm from './some-client';
const smCli: sm.Client = new sm.Client();

export const getKey = async () => {
  const smCreds = await sm.getCreds();
  await smCli.login(smCreds);
};

index.test.ts:

import * as sm from './some-client';
import { getKey } from './';

jest.mock('./some-client');

const smClientMock = sm.Client as jest.MockedClass<typeof sm.Client>;
const smGetCredsMock = sm.getCreds as jest.MockedFunction<typeof sm.getCreds>;

describe('74516778', () => {
  test('should pass', async () => {
    smGetCredsMock.mockResolvedValue({ pwd: '123' });
    await getKey();
    expect(smClientMock).toBeCalledTimes(1);
    expect(smGetCredsMock).toBeCalledTimes(1);
    const smClientInstanceMock = smClientMock.mock.instances[0];
    expect(smClientInstanceMock.login).toBeCalledWith({ pwd: '123' });
  });
});

Test outcome:

 PASS  stackoverflow/74516778/index.test.ts (8.48 s)
  74516778
    ✓ should pass (3 ms)

----------------|---------|----------|---------|---------|-------------------
File            | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------------|---------|----------|---------|---------|-------------------
All files       |   76.92 |      100 |   33.33 |    87.5 |                   
 index.ts       |     100 |      100 |     100 |     100 |                   
 some-client.ts |      50 |      100 |       0 |   66.67 | 2                 
----------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        9.278 s, estimated 10 s

Package version used:

"jest": "^26.6.3",

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

There seems to be a syntax error in the regular expression used in Angular TypeScript

I've encountered an error and I'm struggling to identify the syntax issue. core.mjs:6495 ERROR SyntaxError: Invalid regular expression: /https://graph.microsoft.com/v1.0/communications/callRecords/getPstnCalls(fromDateTime=2020-01-30,toDateTime ...

Testing Material UI withStyles Component with Shallow Rendering in Jest

I am currently working on testing a component that is using withStyles() from Material UI and Jest. My goal is to test the child elements, but I am encountering an issue where my wrapper is coming up as undefined. While I have come across similar posts ab ...

Running tests using gruntJS is a simple process that involves setting up your

Interested in learning how to execute the test suite using gruntjs? I initially assumed it would be easy and clear-cut, but I encountered some challenges :) I presumed that simply typing "grunt test" would suffice for running tests in gruntjs. However, th ...

Using a Component as a Property in Angular

There is a small gridComponent: @Component({ selector: 'moving-grid', templateUrl: './grid.component.html', styleUrls: ['./grid.component.css'] }) export class GridComponent { @Input('widgets') ext ...

Exploring the Possibilities: Incorporating xlsx Files in Angular 5

Is there a way to read just the first three records from an xlsx file without causing the browser to crash? I need assistance with finding a solution that allows me to achieve this without storing all the data in memory during the parsing process. P.S: I ...

Dependency injection in Angular 2 service not functioning as expected

I am facing an issue while trying to retrieve static data from UserService in Angular 2. Although everything seems correct based on the documentation, it is not functioning as expected. Below is my UserComponent.ts import {Component ,OnInit } from ' ...

Tips for testing validation messages in Angular template-driven forms

I have created a simple Angular template-driven form with one required field. An error message is supposed to be shown if the field is not valid, such as when the component is initially loaded and the required field is empty. The code functions correctly i ...

A Guide to Retrieving Parameters and Request Body using Express and Typescript

When I use the PUT method, I encounter this issue: const createFaceList = (req: Request<{faceListId : string}>, res: Response, next: NextFunction) => { console.log(req.body.name); console.log("faceListID = " + req.params.faceListId); a ...

Angular 5 - Performing Jasmine Testing: Simulating an Error Response on a Genuine HTTP Request

Before I start, I'd like to mention that I am currently in the process of learning Angular 4 as part of an internship. This is all very new to me. Anyway, I have a requirement where I need to simulate an error during an HTTP request in the controller ...

Resolving "SyntaxError: Unexpected identifier" when using Enzyme with configurations in jest.setup.js

I'm currently facing an issue while trying to create tests in Typescript using Jest and Enzyme. The problem arises with a SyntaxError being thrown: FAIL src/_components/Button/__tests__/Button.spec.tsx ● Test suite failed to run /Users/mika ...

Anticipating the completion of multiple observable subscription functions

Is there a way to replace and convert all words in an array using an object's method that returns an observable? I found a helpful solution on this post which uses bind to pass the correct value. After all subscriptions are complete, I want to execut ...

Experiencing problem with TestNG while running tests concurrently and utilizing "priority" attribute

I am dealing with 2 separate classes Class 1: @Test public void test1(){ System.out.println("test1-1"); } @Test(priority = 1) public void test2(){ System.out.println("test2-1"); } @Test(priority = 6) public void test3(){ System.out.println( ...

"Upload a video file and use JavaScript to extract and save the first frame as an image

I have a webpage where users can upload a video file, and the page will generate a thumbnail based on a timestamp provided by the user. Currently, I am focusing on generating the thumbnail from the FIRST frame of the video. Here is an example of my progr ...

Creating Apache Arrow vectors in TypeScript for writing data to a Table

Currently, I am in the process of creating a method that is designed to take a column of data, referred to as data: any[], and then pack it into an Arrow-typed Array Buffer for insertion into an Arrow table. To illustrate with an example, if we consider T ...

Ag-grid with Angular 2 allows users to easily edit entire columns with just a few

I need help modifying a column in my ag-grid. My ag-grid currently looks like this: grid image I want to update all values in the column Etat to be arrêté, but I'm struggling to make it work. This is the code I've been trying: private gridO ...

What does `(keyof FormValues & string) | string` serve as a purpose for?

Hey there! I'm new to TypeScript and I'm a bit confused about the purpose of (keyof FormValues & string) | string. Can someone please explain it to me? export type FieldValues = Record<string, any>; export type FieldName<FormValues ...

Compiling TypeScript to JavaScript with Deno

Currently experimenting with Deno projects and looking for a way to transpile TypeScript into JavaScript to execute in the browser (given that TS is not supported directly). In my previous experience with NodeJS, I relied on installing the tsc compiler via ...

What's causing the "* before initialization" error in Vue with TypeScript?

I am encountering an issue with my code where I get the error "Cannot access 'AuthCallback' before initialization" when attempting to call the router function in the AuthCallback component. What could be causing this problem? The desired function ...

Error: JSON parse error - unexpected character 'a' at index 1

I'm encountering an issue while attempting to change the album title from "cars" to "car". The error message I keep receiving is: SyntaxError: Unexpected token a in JSON at position 1. Any ideas on what might be causing this problem? Below is the cu ...

Tips for incorporating attributes into a customized Material-UI props component using TypeScript in React

I'm interested in using material-ui with react and typescript. I want to pass properties to the components, but I'm having trouble figuring out how to do it. Currently, I'm working with the react-typescript example from the material-UI repos ...