Using Jest functions as object properties results in undefined behavior

I am faced with a challenge in my class where I need to mock an object along with its properties

intercept(context: ExecutionContext) {
  const response = contect.switchToHttp().getResponse() // the chain that needs to be mocked

  if (response.headersSent) { // testing this scenario
    return true
  }

  return false
}

When I simulate the dependency using a regular object literal and some anonymous functions, everything runs smoothly as anticipated

const executionContext = {
  switchToHttp: () => executionContext, // simulates 'this' chaining
  getRequest: () => {
    return {
      url: undefined,
      method: undefined,
      headers: undefined,
      connection: {
        remoteAddress: undefined,
        remotePort: undefined
      }
    }
  },
  getResponse: () => {
    return {
      headersSent: true, // desire an easy way to alter this during testing without resorting to a factory
      append: () => undefined
    }
  }
} as unknown as ExecutionContext

it('test', () => {
  const response = myclass.intercept(executionContext);

  expect(response).toBeTrue()
});

However, when I attempt to mimic some of the properties using jest.fn(), unexpected outcomes surface.

const getResponseSpy = jest.fn(() => {
  return {
    headersSent: false,
    append: () => undefined
  }
});

const executionContext = {
  switchToHttp: () => executionContext,
  getRequest: () => {
    return {
      url: undefined,
      method: undefined,
      headers: undefined,
      connection: {
        remoteAddress: undefined,
        remotePort: undefined
      }
    }
  },
  getResponse: getResponseSpy // provides a more convenient way to modify this 
} as unknown as ExecutionContext

At this stage in my code, the response turns out to be undefined

TypeError: Cannot read property 'headersSent' of undefined

Moreover, if I try something like

getResponse: () => getResponseSpy
, then the response within my code becomes a Jest mock object instead of the mimicked implementation, lacking the headersSent property.

I sense that I might be overlooking a fundamental aspect. I attempted utilizing

switchToHttp: jest.fn().mockResturnThis()

Nevertheless, no alterations occur. It appears that the jest spy inside the object fails to provide its simulated implementation

What could be the issue here?

Answer №1

Using mockFn.mockReturnThis() is essential.

For example:

app.js:

interface UserContext {
  switchToHttp(): UserContext;
  getResponse(): UserContext;
  headersSent: boolean;
}

export const myModule = {
  intercept(context: UserContext) {
    const response = context.switchToHttp().getResponse();

    if (response.headersSent) {
      return true;
    }

    return false;
  },
};

app.test.js:

import { myModule } from './';

describe('87654321', () => {
  it('should succeed', () => {
    const userContext = {
      switchToHttp: jest.fn().mockReturnThis(),
      getResponse: jest.fn().mockReturnThis(),
      headersSent: true,
    };
    const result = myModule.intercept(userContext);
    expect(result).toBeTruthy();
  });
});

Test outcome:

 PASS  examples/87654321/app.test.js (8.387 s)
  87654321
    ✓ should succeed (3 ms)

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |      80 |       50 |     100 |      80 |                   
 app.js   |      80 |       50 |     100 |      80 | 15                
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        9.273 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

What is the best way to reposition the origin of the canvas to the center?

As a beginner in html and JavaScript, I am currently working on a program that involves points and lines in a coordinate system. However, the canvas for html5 has its origin at the upper corner, and I need to create a coordinate system with the origin at ...

Is there a way to retrieve two distinct values from an object?

Is there a way to retrieve two target values from an option using useState in react/nextjs? Here is a sample of my api: const movies = [ { id: 1, name: "Fight Club" }, { id: 2, name: "Titanic" }, { ...

Utilizing Selenium to inject javascript permanently or on every page refresh

In my selenium webdriver test using Python 3, I have implemented a semi-automated process. This means that some routines are automated while other tasks require user interaction with the browser, such as page refreshes or redirects. My challenge is to inj ...

Transfer photos and videos to an external server using Javascript with Meteor framework

I currently have a meteor application hosted on Digital Ocean. I am considering setting up a dedicated server to store all images and videos separately from the site itself. Whenever a user uploads new media, it will be saved to this separate server. Does ...

What is the process for transforming a method into a computed property?

Good day, I created a calendar and now I am attempting to showcase events from a JSON file. I understand that in order to display a list with certain conditions, I need to utilize a computed property. However, I am facing difficulties passing parameters to ...

Exporting a module with Node.js is a crucial aspect of building

Within my custom module, I have successfully set up an export function. module.exports = function(callback) { var request = require("request") var url = "http://sheetsu.com/apis/94dc0db4" request({ url: url, json: true }, ...

What could be the reason for my button to update only at the completion of the "each" loop?

Is there a way to update the button text before the loop, so that users can receive feedback while it's running? Currently, the text only updates after the loop has completed. In my scenario, the button displays "Updating please wait..." after the lo ...

Having trouble submitting a date input form generated with vuejs on Safari browser

I am a huge fan of Vuejs and it's my go-to at work. The other day, I came across a rather perplexing scenario. If you have any insights into this, please do share. Here is the code in question: <script setup lang="ts"> import { ref ...

Is RaphaelJS truly a vector-based tool?

Is it possible to position a circle at 50% of the width of the canvas using RaphaelJS without having to calculate the exact pixel value? I am looking for a simple way to place an element at half its container's width, but I'm not sure if this can ...

Tips for saving JSON information into a variable using JavaScript

I am in need of a function called ** getJson () ** that can fetch and return data from a json file. Here is the JSON data (file.json): [ { "01/01/2021":"Confraternização Universal", "1 ...

I'm experiencing an issue with my website where it appears broken when I build it, but functions properly when I use npm run dev in Next

For my project, I have utilized NextJs, Tailwind, React, and Typescript. It is all set and ready to be hosted. After using "output: export" in next.config.js and running npm run build, the process was successful. However, when viewing my website locally, I ...

Blending TypeScript declaration files and Node.js require across various files within an internal module

Is it problematic to mix Node.js modules (require) with TypeScript definition files (d.ts) multiple times within a module? In my case, I organize my modules into namespaces per folder similar to how it's done in C#. After compiling them all using tsc ...

An interesting result from using fs.appendFile: the mysterious [object Object]

When utilizing console.log, the output of req.query (request.query) appears correct as { name: 'sean', comments: 'Hey' }. However, the issue arises when attempting to write this data to a file using fs.appendFile, as it ends up being wr ...

Enhancing Connectivity Through Fastify and Fastify-HTTP-Proxy Integration

I'm currently utilizing fastify along with fastify-http-proxy on a VPS running Ubuntu 19.x that is equipped with three unique IPv4 addresses. I have confirmed the functionality of these IP addresses by testing them using the following example IPs: cur ...

The useReducer function dispatch is being called twice

I can't figure out the reason behind this issue. It seems that when strict mode is enabled in React, the deleteItem function is being executed twice. This results in the deletion of two items instead of just one - one on the first round and another on ...

Having trouble creating a unit test for exporting to CSV in Angular

Attempting to create a unit test case for the export-to-csv library within an Angular project. Encountering an error where generateCsv is not being called. Despite seeing the code executed in the coverage report, the function is not triggered. Below is the ...

Assist in troubleshooting and pinpointing the solution to this issue

function generateRandomString(length) { var result = ""; var characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"; var charactersLength = characters.length; for (var i = 0; i < length; i++) { result += characters ...

Determine the current directory being called in Grunt, without confusing it with the directory of the gruntfile

If Grunt is installed in a folder called /foo, but my current directory is /foo/bar/baz, and I execute "grunt sometask" from within my current directory, how can I programmatically determine the path of the current directory where Grunt was called? In othe ...

Issue encountered when transferring properties to create a search bar

My goal is to create a search input that filters based on the user's input. I have two components - one with the search input (app.js) and the other with the table (table.js). In the search input component (app.js), I can retrieve the current value b ...

Tips for preventing the need to cast a DOM element to any in Typescript

In my Typescript code, I am retrieving the value of a DOM element like this: document.getElementById('MyElementId') as HTMLElement).value I feel unsure about casting it to HTMLElement. Is there a better way to specify the type and retrieve this ...