Using ts-jest for mocking internal modules

Within my .ts module, I have the following code:

import client from './client';

export default class DefaultRequest implements IRequest {
    make(req: Request): Promise<Response> {
        return new Promise<Response>((resolve, reject) => {
            client.post(req, (error: Error | null, res: Response) => {
                if (error) {
                    return reject(error);
                } else {
                    return resolve(res);
                }
            });
        });
    }
}

I am attempting to create a unit test for this class using ts-jest in order to mock the behavior of client and ensure it returns a valid Response.

This is how I am proceeding:

import {mocked} from 'ts-jest/utils';
import client from './client';
import DefaultRequest from './request'

const mockedClient = mocked(client, true);
const testRequest = new DefaultRequest();

jest.mock('./client', () => {
  return {
    RestClient: jest.fn().mockImplementation(() => {
      return {
        post: () => {return someValidResponse();},
      };
    })
  };
});

describe('My Tests', () => {

    it('Unit Test 1', async () => {
        let res: Response = await testRequest.make(buildReq());
    });
});

However, the mockedClient remains unmocked. Here is the content of ./client.ts:

import { RestClient } from '@rest/client';

export default new RestClient();

Is there a way to successfully mock the internal client module used by the DefaultRequest class in this scenario?

EDIT: I also attempted using jest.spyOn

const spiedMethod= jest.spyOn(client, 'post');
        const call: Request = new Request();
        const response: Response = await call.make(buildRequest());

        expect(spiedReleaseMethod).toHaveBeenCalled();
        expect(response.getResponsecode()).toBe(200);

Unfortunately, the original method is still being called instead of the spied method.

Answer №1

When testing the request.ts module which relies on the client.ts module, it is important to create a mock for the client.ts module and its post method instead of the @rest/client package.

For example:

request.ts:

import client from './client';

interface IRequest {
  make(req: Request): Promise<Response>;
}

export default class DefaultRequest implements IRequest {
  make(req: Request): Promise<Response> {
    return new Promise<Response>((resolve, reject) => {
      client.post(req, (error: Error | null, res: Response) => {
        if (error) {
          return reject(error);
        } else {
          return resolve(res);
        }
      });
    });
  }
}

client.ts: (The specific package implementation of the client does not matter, as long as the exposed interfaces are consistent)

export default {
  post(req, callback) {
    console.log('real implementation');
  },
};

request.test.ts:

import { mocked } from 'ts-jest/utils';
import client from './client';
import DefaultRequest from './request';

jest.mock('./client');

const mockedClient = mocked(client);

describe('68115300', () => {
  afterAll(() => {
    jest.resetAllMocks();
  });
  it('should pass', () => {
    mockedClient.post.mockImplementationOnce((req, callback) => {
      callback(null, 'mocked response');
    });
    const testRequest = new DefaultRequest();
    testRequest.make(('req' as unknown) as Request);
    expect(mockedClient.post).toBeCalledWith('req', expect.any(Function));
  });
});

Test Result:

 PASS  examples/68115300/request.test.ts (12.448 s)
  68115300
    ✓ should pass (3 ms)

------------|---------|----------|---------|---------|-------------------
File        | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
------------|---------|----------|---------|---------|-------------------
All files   |   77.78 |       50 |      75 |   77.78 |                   
 client.ts  |      50 |      100 |       0 |      50 | 3                 
 request.ts |   85.71 |       50 |     100 |   85.71 | 12                
------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        14.61 s

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

`It is important to note that in Tailwind CSS, `h-8` does not supersede `h-4

I developed an Icon component that looks like this: import { IconProp, library } from "@fortawesome/fontawesome-svg-core"; import { far } from "@fortawesome/free-regular-svg-icons"; import { fas } from "@fortawesome/free-solid-svg- ...

Exploring the depths of Javascript objects using Typescript

If I have this specific dataset: data = { result: [ { id: '001', name: 'Caio B', address: { address: 'sau paulo', city: 'sao paulo', ...

What is the method for assigning a value to an attribute in HTML?

Is there a way to assign a function's value to an HTML attribute? For example, setting the attribute value to the value returned by the function foo. foo () : string { return "bar"; } I attempted the following without any success. <input type="b ...

Resolving Node.js Absolute Module Paths with TypeScript

Currently, I am facing an issue where the modules need to be resolved based on the baseUrl so that the output code is compatible with node.js. Here is my file path: src/server/index.ts import express = require('express'); import {port, database ...

Validation error from Express-validator may result in TypeScript error: the request.query object could potentially be undefined

Recently, as I was developing a Node.js app using express, I decided to enhance it with express-validator. Despite being new to express-validator, the warnings it generated perplexed me due to its lack of detailed documentation. To illustrate my point, he ...

How can I change an icon and switch themes using onClick in react js?

I have successfully implemented an icon click feature to change the colorscheme of my website (in line 21 and changeTheme). However, I also want the icon to toggle between FaRegMoon and FaRegSun when clicked (switching from FaRegMoon to FaRegSun and vice v ...

Tips for adjusting the dimensions of a child element to match its parent in Angular 12 with Typescript

I have included the child component in the parent component and I am displaying that child component within a col-md-8. What I want to achieve is to highlight a specific div in the child component with additional text, making it equal in size to the parent ...

Generating an array of strings that is populated within the Promise handler

If I come across code like this in my Ionic/Angular/TypeScript project... let arr: Array<string> = []; this.databaseProvider.getAllSpecies().then(allSpecies => { for(let species of allSpecies) { if(species.name.toLowerCase().indexOf(keyword ...

Transforming API data into a particular type using Typescript

I am looking to extract only specific properties from a given object. Can TypeScript interfaces be used to iterate through the data and eliminate unnecessary properties? Sample data: [ 0: { "original_language" : "en", "t ...

What is the best way to modify an existing object in an Observable Array in Angular?

As I work on my Ionic 5 / Angular application, a challenge arises when attempting to update a Conversation object within the existing array of Conversation: private _conversations = new BehaviorSubject<Conversation[]>([ new Conversation( & ...

What is the best way to handle multiple requests to the same URL in Cypress while waiting?

I am currently developing a Cypress test that involves sending multiple requests to the same URL with varying body content. Essentially, the test modifies input values in the user interface, triggering new server requests. The challenge arises when trying ...

Developing UIs in React that change dynamically according to the radio button chosen

Problem Statement I am currently developing a web application feature that computes the heat insulation factor for a specific area. You can view the live demonstration on Codesandbox <a href="https://codesandbox.io/p/github/cloudmako09/btu-calc/main?im ...

What is the method for defining a constant data type with a class property data type in typescript?

I've been working on developing a nestjs API and have been using classes to define my entities. For instance, I have created a Customer entity as shown below: export class Customer { id: number; name: string; } Now, while working on my Custom ...

Experience Next.js 13 with Chakra UI where you can enjoy Dark Mode without the annoying White Screen Flash or FOUC (flash of unstyled content)

Upon refreshing the page in my Next.js 13 /app folder application using Chakra UI, I notice a few things: A momentary white flash appears before switching to the dark theme. The internationalization and font settings momentarily revert to default before l ...

Ionic causing delay in updating ngModel value in Angular 2

My ion-searchbar is set up like this: <ion-searchbar [(ngModel)]="searchQuery" (keyup.enter)="search();"></ion-searchbar> In the typescript file, the searchQuery variable is defined as follows: export class SearchPage { searchQuery: string ...

Prevent the click event on an Angular component

I am currently utilizing the component found on this link: I have not been able to locate a function or property that disables the component state, making it impossible to select dates on the calendar. Due to this limitation, I am interested in learning ...

What is the best way to handle missing values in a web application using React and TypeScript?

When setting a value in a login form on the web and no value is present yet, should I use null, undefined, or ""? What is the best approach? In Swift, it's much simpler as there is only the option of nil for a missing value. How do I handle ...

Accessing the Parent Variable from a Function in JavaScript: A Guide

How can you properly retrieve the value of x? let x = 5 const f = (n:number) => { let x = "Welcome"; return x * n // Referring to the first x, not the second one } Also, what is the accurate technical term for this action? ...

Exploring the Power of Chained Promise Calls

Afterwards, in the .then section, I call another promise for an HTTP request: .then(result => { this.service().then(data => {}); }); Would you say that using chained promises in this manner is correct? ...

Creating an interface for a class instance through the implementation of a class constructor

I am working on an application where developers can specify which component they want to render a certain part. I need users to understand that they must implement an interface, but I'm struggling with correctly writing the typing. export interface I ...