How do I go about mocking a function from a third-party nodejs module when using TypeScript with jest?

I need help with mocking a function from a third-party node module in jest, specifically the fs.readFileSync() function. I have come across several examples online, but I haven't found one that incorporates TypeScript. To illustrate my question, I have provided a straightforward example on GitHub. If anyone familiar with jest could assist me with this issue, it would be greatly appreciated.

Answer №1

Below are a variety of ways to mock something similar to fs.readFileSync():

Mock the function

To mock a function, utilize jest.spyOn() in conjunction with methods like mockImplementation():

import { returnNameInJsonFile } from './index';
import * as fs from 'fs';

describe('index', () => {

  it('returnNameInJsonFile', () => {
    const mock = jest.spyOn(fs, 'readFileSync');  
    mock.mockImplementation(() => JSON.stringify({ name: 'myname' }));

    const name: string = returnNameInJsonFile('test.json');
    expect(name).toBe('myname');

    mock.mockRestore();  
  });

});

Mock the module using a factory

Supply a module factory to jest.mock():

import { returnNameInJsonFile } from './index';

jest.mock('fs', () => {
  const MOCK_FILE_INFO = { 'test.json': JSON.stringify({ name: 'myname' }) };
  return {
    readFileSync: (fpath, opts) => {
      if (fpath in MOCK_FILE_INFO) {
        return MOCK_FILE_INFO[fpath]
      }
      throw 'unexpected fpath'
    }
  }
});

describe('index', () => {
  it('returnNameInJsonFile', () => {
    const name: string = returnNameInJsonFile('test.json');
    expect(name).toBe('myname'); 
  });
});

Mock the module automatically

Create a mock for the module.

Jest will automatically use the mock unless it is a core Node module (like fs), in which case calling jest.mock() is necessary.

__mocks__/fs.ts:

const fs = jest.genMockFromModule('fs');

let mockFiles: object = {};

function __setMockFiles (newMockFiles: object) {
  mockFiles = newMockFiles;
}

function readFileSync(filePath: string) {
  return mockFiles[filePath] || '';
}

// If anyone knows how to avoid the type assertion feel free to edit this answer
(fs as any).__setMockFiles = __setMockFiles;
(fs as any).readFileSync = readFileSync;

module.exports = fs;

index.test.ts:

import { returnNameInJsonFile } from './index';

jest.mock('fs'); 

describe('index', () => {

  const MOCK_FILE_INFO = { 'test.json': JSON.stringify({ name: 'myname' }) };

  beforeEach(() => {
    require('fs').__setMockFiles(MOCK_FILE_INFO);
  });

  it('returnNameInJsonFile', () => {
    const name: string = returnNameInJsonFile('test.json');
    expect(name).toBe('myname'); 
  });
});

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

Exploring the serverless framework's Choice Activity with Logical Operators

Here is a simple Choice Activity in the serverless.yml file: CheckActionType: Type: Choice Choices: - Variable: "$.results.ACTION" StringEquals: "CREATED" Next: CreateOrder ...

What is the best way to implement persistStore in Redux-Toolkit?

Here is my setup: import AsyncStorage from '@react-native-async-storage/async-storage' import { persistStore, persistReducer } from 'redux-persist'; import { configureStore } from "@reduxjs/toolkit"; import { searchReducer } f ...

Granting permission for npx command to create a directory

I encountered an issue while trying to use the npx create-react-app command. Previously, I had the create-react-app installed globally on my system and used the npm create-react-app command. However, I discovered that utilizing npx ensures the utilizati ...

Caught up: TypeScript not catching errors inside Promises

Currently, I am in the process of developing a SPFx WebPart using TypeScript. Within my code, there is a function dedicated to retrieving a team based on its name (the get() method also returns a promise): public getTeamChannelByName(teamId: string, cha ...

Is it possible to run two Livescript (a fork of Coffeescript) applications using just one globally installed package?

I am currently using a modified version of Coffeescript called LiveScript for my application development. To execute files, I typically use the lsc command like this: $ lsc app.ls Recently, there was an update that changed the way modules are required. ...

Publishing Typescript to NPM without including any JavaScript files

I want to publish my *.ts file on NPM, but it only contains type and interface definitions. There are no exported JavaScript functions or objects. Should I delete the "main": "index.js" entry in package.json and replace it with "main": "dist/types.ts" inst ...

Angular is unable to access functions or variables within a nested function

I am currently utilizing google.maps.geocoder to make location requests within my Angular app. When I provide a callback function with the results, it leads to unexpected code breaks when trying to call another function that displays map markers. It seem ...

What is the best way to define a function that accepts an object with a specific key, while also allowing for any additional keys to be passed

Typescript allows us to define an interface for an object that must have a key and can also allow additional keys: interface ObjectWithTrace { trace: string; [index: string]: any } const traced: ObjectWithTrace = { trace: 'x', foo: 'bar ...

In TypeScript, leveraging the spread operator to determine the largest value in an array containing nullable numbers

Having an array of nullable numbers presented in the following way: let myArray : Array<number | null> = [1,2,null,4,null,5]; let maximumOfMyArray = Math.max(...myArray); // Type null is not assignable to type number I am content with JavaScript tre ...

A guide on incorporating a set of components to be utilized as custom HTML elements in Angular

I am in the process of revamping my application to be more modular on the UI side, with a focus on separating different elements including: App header Left navigation panel Main content on the right side of the nav panel I have successfully figured out ...

Ways to parse the data from a response received from an Axios POST request

After sending the same POST request using a cURL command, the response I receive is: {"allowed":[],"error":null} However, when I incorporate the POST request in my code and print it using either console.log("response: ", resp ...

WARNING: Firebase alert - Incorrect query string segment detected during deployment of basic Firebase Cloud function

Upon waking up this morning, I was bombarded with a multitude of "FIREBASE WARNING: Invalid query string segment" errors in my functions log. Determined to get to the bottom of it, I made numerous changes to my functions and redeployed all my cloud functio ...

Exploring the functionality of the WHERE function in Firebase with Angular

Current Objective: Our main focus here is to allow users to post within their designated Organization Group. These posts should remain exclusively visible within the specific Organization Group they are posted in. To achieve this, I have attempted to impl ...

Is there a way to substitute the HOC with a single call and solely modify the prop?

One issue I've encountered in my project is the repetitive use of a Higher Order Component (HOC) for the header. Each time it's used, the props are set to determine whether header links should be displayed or not. My objective is to streamline th ...

Tips on personalizing the formatting alert in Webclipse for Angular 2 using Typescript

Webclipse offers extensive formatting warnings for TypeScript code, such as detecting blank spaces and suggesting the use of single quotes over double quotes. However, some users find the recommendation to use single quotes annoying, as using double quotes ...

Executing a Bash script using NPM with several arguments

I've developed a bash script to streamline the git release process by accepting one or multiple branch names as arguments. When using it in the terminal, I can do so with: ./releaseGit.sh -b branch1 -b branch2 However, I'd like to utilize this ...

Is there a way to use WithStyles<typeof styles> within Material UI?

import { WithStyles, createStyles } from '@material-ui/core'; const styles = (theme: Theme) => createStyles({ root: { /* ... */ }, paper: { /* ... */ }, button: { /* ... */ }, }); interface Props extends WithStyles<typeof styles> ...

Using parametric types as type arguments for other types in TypeScript or Flow programming languages

Consider the various types showcased for demonstration: type TranslateToEnglish<A extends string> = A extends "1" ? "one" : A extends "2" ? "two" : A extends "3" ? "three" : "e ...

methods for obtaining the currently selected month

After installing the npm package v-calendar@next and @popperjs/core, I am unsure of how to retrieve the value. Can someone guide me on how to display information about the currently selected value for the month? //. //. //. //. <script> export defa ...

Using Typescript does not generate any errors when indexing an object with brackets

One interesting thing I've noticed about TypeScript is that it allows me to use bracket notation to access an object via index, even when it only has keys. For example: interface testObject { name: string; id: number; } let first: testObject ...