Resetting the mocked dependency in Jest and Supertest: a handy guide

I seem to be encountering an issue with resetting jest mocks of a dependency after it has been used once by supertest. Any help or tips would be greatly appreciated.

Below is my API test utilizing supertest:

import request from 'supertest';
import router from '../index';
const app = require('express')();
app.use(router);

jest.mock('config', () => ({}));

jest.mock('express-request-proxy', () => data => (req, res, next) =>
  res.json(data),
);

beforeEach(() => {
  jest.resetAllMocks();
});

describe('GET /', () => {
  it('should get all stuff', () =>
    request(app)
      .get('')
      .expect(200)
      .expect('Content-Type', /json/)
      .then(response => {
        expect(response.body).toMatchSnapshot();             // all good here 
      }));

  it('should get all stuff when FOO=bar', async () => {
    jest.mock('config', () => ({
      FOO: 'bar',
      get: key => key,
    }));

    // >> HERE <<
    // config.FOO is still undefined!
    // reseting mocks did not work ...
    await request(app)
      .get('')
      .expect(200)
      .expect('Content-Type', /json/)
      .then(response => {
        expect(response.body.query).toHaveProperty('baz');   // test fails ...
      });
  });
});

Here is the express.js API code:

const router = require('express').Router({ mergeParams: true });
import config from 'config';
import proxy from 'express-request-proxy';

router.get('', (...args) => {
  let query = {};
  if (config.FOO === 'bar') {
    query.baz = true;
  }
  return proxy({
    url: '/stuff',
    query,
  })(...args);
});

Answer №1

When working with Jest, it's important to remember that you can't use jest.mock(moduleName, factory, options) within a function scope - it should be used at the module scope instead. For function scope mocking, utilize jest.doMock(moduleName, factory, options).

Before running each test case, make sure to include jest.resetModules() to reset the module registry and clear the cache of all required modules.

This approach ensures that your ./config module registry is refreshed, providing different mocked values for each test case when requiring it post-jest.doMock('./config', () => {...}) declaration.

If you opt for the { virtual: true } option, it signifies that the express-request-proxy package isn't installed in your npm_modules directory. You can omit this option if the package is already installed.

For a unit test solution:

index.js:

const router = require('express').Router({ mergeParams: true });

import config from './config';
import proxy from 'express-request-proxy';

router.get('', (...args) => {
  console.log(config);
  let query = {};
  if (config.FOO === 'bar') {
    query.baz = true;
  }
  return proxy({ url: '/stuff', query })(...args);
});

export default router;

config.js:

export default {
  FOO: '',
};

index.test.js:

import request from 'supertest';

jest.mock('express-request-proxy', () => (data) => (req, res, next) => res.json(data), { virtual: true });

beforeEach(() => {
  jest.resetAllMocks();
  jest.resetModules();
});

describe('GET /', () => {
  it('should get all stuff', () => {
    jest.doMock('./config', () => ({}));
    const router = require('./index').default;
    const app = require('express')();
    app.use(router);

    return request(app)
      .get('')
      .expect(200)
      .expect('Content-Type', /json/)
      .then((response) => {
        expect(response.body).toMatchSnapshot();
      });
  });

  it('should get all stuff when FOO=bar', async () => {
    jest.doMock('./config', () => ({
      default: {
        FOO: 'bar',
        get: (key) => key,
      },
      __esModule: true,
    }));
    const router = require('./index').default;
    const app = require('express')();
    app.use(router);

    await request(app)
      .get('')
      .expect(200)
      .expect('Content-Type', /json/)
      .then((response) => {
        expect(response.body.query).toHaveProperty('baz');
      });
  });
});

Unit test outcomes with full coverage report:

 PASS  stackoverflow/61828748/index.test.js (11.966s)
  GET /
    ✓ should get all stuff (8710ms)
    ✓ should get all stuff when FOO=bar (24ms)

  console.log
    {}

      at stackoverflow/61828748/index.js:7:11

  console.log
    { FOO: 'bar', get: [Function: get] }

      at stackoverflow/61828748/index.js:7:11

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |     100 |      100 |     100 |     100 |                   
 index.js |     100 |      100 |     100 |     100 |                   
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   1 passed, 1 total
Time:        13.268s

index.test.js.snap:

// Jest Snapshot v1

exports[`GET / should get all stuff 1`] = `
Object {
  "query": Object {},
  "url": "/stuff",
}
`;

Source code available at: https://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/stackoverflow/61828748

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

Guide to implement a confirmation box in PHP

I recently set up a Joomla article and integrated the Sourcerer Joomla extension to include JavaScript and PHP in my project. Currently, I am developing a course purchase site where users can buy courses from owners and credits are deducted upon every purc ...

Error: The regular expression flags provided are invalid for the Partial View

I am currently facing an issue with a div in my View that uploads a PartialView. Below is the code snippet: <div id="right2" style="border-style: solid; border-color: #1d69b4; border-radius: 10px;"> @Html.Partial("CalendarDefault") </div ...

Calculate the quantity of items within a JSON object that possess specific characteristics

Here is some JSON information: {"people": [ { "firstName" : "Paul", "lastName" : "Taylor", "hairCount": 2 }, { "firstName" : "Sharon", "lastName" : "Mohan", "hairCount": 3 }, { "firstName" : "Mohan", "lastName" : "Harris", "hairCount": 3 }, ...

Understanding the distinction between using socket.io to create an HTTP server and not creating one is essential for

I'm currently working on creating a new notification system using nodejs with the help of socket.io. Can someone explain the difference between the following two code snippets? Code Snippet 1: //Setting up an HTTP server and establishing a Socket con ...

Utilizing the require pattern to integrate JavaScript functionality into HTML

Have: project |- consume_script.js |- index.html Need index.html to be like: <html> <head> </head> <body> <script src="consume_script.js"></script> </body> </html> Issue: consume_script ...

Tips on adding a tooltip to the react-bootstrap tab element

How can I add a tooltip to the tabs in my React application using Bootstrap tabs? I have three tabs and I want a tooltip to appear when hovering over each tab. import { Tabs,Tab} from "react-bootstrap"; // inside return <Tabs variant="pills" ...

Navigating Successful or Unsuccessful Payment Routing within the Razorpay System

Recently started exploring Payment Gateway Integration and need assistance. I am looking for guidance on redirecting a URL after successful or failed payments in Razorpay. I need JavaScript code for this purpose. I believe the handler function can be util ...

Issue with AJAX Complete event not functioning

Currently, I am facing an issue with firing the .ajaxComplete function on a demo site. I have referred to this function from this link. Below is my code : <SCRIPT type="text/javascript"> <!-- /* Credits: Bit Repository Source: http://www.bit ...

Integrating socket.io into the MVC structure of an express project: A step-by-step guide

I'm currently working on setting up a backend using socket.io and express, but I'm encountering issues connecting the sockets to my frontend built with nextjs. Upon entering a page, a fetch request is made that should establish a connection with ...

Tips for displaying the html content saved in the database onto an ejs webpage

This task seems simple, but I'm struggling to solve it. In my Node.js/Express webapp, I have the Quill.js editor installed. It stores my description in MySQL DB like this: <p><strong>This is the quill data. How are we doing dev?</stron ...

Problem encountered when attempting to use 'delete' as a property name

I am currently encountering an issue with a form that deletes a gallery from a database. Previously, the code was functioning properly but after some recent updates such as switching from jquery.interface to jquery-ui, I am now facing difficulties. Wheneve ...

Mastering Vue 3: Simplifying a reactive array of objects while maintaining reactivity

Struggling with maintaining reactivity in Vue 3 when flattening a nested array of objects. Unfortunately, my attempts result in crashing and browser hang-ups. In my Vue 3 component, I have an array structured as a list of objects: this.grouped = [ ...

Is there a way to send a file with React? Or are there similar methods like `npm unload` for Express?

Is there a way to send files using React similar to express' sendFile method? For example, in express, sending an .exe file would prompt a download, a PDF file would be displayed in the browser, and an image file would also be displayed. I'm curi ...

Can React.js be seamlessly integrated with Apache Wicket?

I have an older web application built with Apache Wicket and I'm interested in exploring the option of adding a new feature using React.js. Can this be done? I've begun looking into it, but haven't come across any helpful resources yet. Cu ...

ESLint guidelines for handling statements with no content

Oops, I made a mistake and ended up with some pretty subpar code. Initially, I meant to write this: let a = 0; ... a = 2; Instead of assigning to a, however, I mistakenly used double equals sign = let a = 0; ... a == 2; I am aware that it is technically ...

JavaScript Date object inconsistency

I've been struggling with getting this system to function properly. Here's the issue I'm facing. The dates I receive from the REST API come in various formats (mm-dd-yyyy-timezone, mm-dd-yyy hh:mm:ss, yyyy-mm-dd-timezone, yyyy-mm-dd hh:mm:s ...

How can an ESM-only package be included using the require method?

My current situation involves a node dependency that was previously included in version 2 using require. However, with the release of version 3, the library can now only be included with import. I encountered the following error: [ERR_REQUIRE_ESM]: requi ...

Tips for executing mocha tests using a reporter

Whenever I execute the command npm test, it displays this output: mocha ./tests/ --recursive --reporter mocha-junit-reporter All the tests are executed successfully. However, when I attempt to run mocha with ./tests/flickr/mytest --reporter junit-report ...

Using Meteor: Sharing a variable among all methods in Meteor

Just dipped my toes into the world of Meteor and managed to create a simple turn-based multiplayer game. When player 2 joins the game, I update the Game collection using a Meteor.method. However, when I try to retrieve that update in another Meteor.method ...

Leveraging jQuery to dynamically load an icon based on the content within a <label> tag

I manage a website that dynamically fetches content from a database, with varying contents for each label. For example, one label may be generated as General:, while another may be generated as TV:. My question is, can jQuery be used to replace the text NA ...