Incorporating Jest to fake the Express Response.setHeader method: A guide

I developed a unique Express middleware that validates if the request content type is JSON. If it's not, the server will return a 415 error along with a custom error object.

import { Request, Response, NextFunction } from "express";

function enforceContentTypeApplicationJson() {
  return (request: Request, response: Response, next: NextFunction) => {
    if (!request.is("application/json")) {
      response.setHeader('Content-Type', 'application/json');
      response.statusCode = 415;

      const actualContentType = request.get("Content-Type") ?? "";
      const errorResult = {
        isSuccessful: false,
        error: `Expected Content-Type 'application/json' but got '${actualContentType}'.`,
      };

      response.json(errorResult);

      return;
    }

    next();
  };
}

To validate this middleware using Jest, I've written my initial test as follows:

  it("checks for status code 415 when header 'Content-Type' is not 'application/json'.", () => {
    const contentType = "multipart/form-data";
    const mockRequest: Partial<Request> = {
      headers: {
        "Content-Type": contentType,
      },
      is: jest.fn().mockImplementation(() => false),
      get: jest.fn().mockImplementation(() => contentType),
    };
    const mockResponse: Partial<Response> = {
      json: jest.fn(),
      setHeader: jest.fn().mockImplementation(function (name, value) {
        (this as unknown as Response).setHeader(name, value);
      }),
    };

    const nextFunction: NextFunction = jest.fn();

    const expectedResponse = {
      isSuccessful: false,
      error: `Expected Content-Type 'application/json' but got '${contentType}'.`,
    };

    const middleware = enforceContentTypeApplicationJson();

    middleware(mockRequest as Request, mockResponse as Response, nextFunction);

    expect(mockResponse.statusCode).toBe(415);
    // expect(mockResponse.getHeader('Content-Type')).toBe('application/json');
    // expect(mockResponse.getHeaders?.()["Content-Type"]).toBe('application/json');
    // expect(mockResponse.getHeader?.("Content-Type")).toBe('application/json');
    expect(mockResponse.json).toBeCalledWith(expectedResponse);
  });

However, I'm facing an issue with mockResponse.setHeader causing the testrunner to throw an error:

this.setHeader is not a function

How can I effectively mock the setHeader method for the Response type? I aim to create a mock implementation to also assert on the response content-type by providing a mock for the getHeader method in the future.

Answer №1

Arrow functions do not have their own bindings to the this keyword. There is no need to mock the implementation for mockResponse.setHeader in that way. Simply using

mockResponse.setHeader = jest.fn()
is sufficient, similar to the mockResponse.json() method.


UPDATE

I fail to see any purpose in storing the headers and retrieving them later for assertion. The mockResponse object is a mock entity, not an actual response object. Therefore, there is no justification for saving the headers within mockResponse.

You can perform an assertion like this:

mockResponse.setHeader.toHaveBeenCalledWith('Content-Type', 'application/json')

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

Having difficulty with utilizing array.every() properly, leading to inaccurate results

Struggling to validate an array of IDs using a custom validator in a nestjs project. The issue arises when passing the array of IDs to a service class for database querying, as the validation always returns true even with incorrect IDs. Snippet of the cus ...

Interact with visible elements by automating mouse clicks with puppeteer

When attempting to click on various elements within a page, my goal is to do so only if they are visible. While achieving this in selenium with the is_displayed method was simple, I have struggled to find a similar approach in puppeteer. I attempted to imp ...

Refining/searching with selectors in AJAX response

As someone who is new to javascript and coding in general, I am facing a challenge with filtering and manipulating data received through an AJAX request. Unfortunately, I do not have access to the server-side code. The server responds with rota information ...

progressing both forward and backward through every month

I am currently working on a project that involves creating a calendar using JavaScript. I have implemented functionalities where I can navigate back and forth through months, fetching the days within each month. However, I am facing an issue where if I go ...

What steps should I take to address the error message "TypeError: express-validator is not a function

I am currently utilizing express-validator version 6.4.0 and encountering an error when running the server. I have attempted to implement custom validation by organizing separate files for validator, controller, and routes. Here is the primary server file ...

Stopping HTTP client calls in OnDestroy hook of an Angular Service

Is it possible to automatically unsubscribe from an http call in an Angular service using the ngOnDestroy hook? Just to note, I am already familiar with using the rxjs 'take' operator or manually unsubscribing from the service within the compone ...

Troubles encountered with example code: Nested class in an exported class - Integrating Auth0 with React and Node.js

I am currently attempting to execute tutorial code in order to create an authentication server within my React project. Below is the code snippet provided for me to run: // src/Auth/Auth.js const auth0 = require('auth0-js'); class Auth { co ...

Difficulty arises when transferring files in Node.js from one directory to another

Attempting to use node.js to transfer files from the currentFolder(root of project)/node_modules/mime/ to currentFolder(root of project)/files/, encountering an error: events.js:85 throw er; // Unhandled 'error' event ^ Error: ...

Chrome is failing to set the cookies that are being sent

I have tried numerous combinations and looked at similar questions, but nothing seems to be working for me. Just to clarify, I am running everything on localhost. regUser = () => { var username = getE("username-input").value; var e ...

Guide to setting up jQuery Mobile with bower

For my project, I'm interested in utilizing jquery-mobile through bower. In order to do so, I need to execute npm install and grunt consecutively within the bower_components/jquery-mobile directory to access the minified .js and .css files. This pro ...

Updating a specific index within an array of objects in a Mongoose-Express server

I have set up a unique identifier ID and I am attempting to modify my coins as well as the first array object's purchased boolean value to true. This is an example of how my data appears: [ { "identifier": "123456789&q ...

"Unlocking the power of AngularJS translate: A step-by-step

I'm seeking answers to two questions. 1) How can I utilize angularjs translate with ng-repeat? Although my Json file works fine, the text does not display when using ng-repeat. Here is a snippet from my json: "rules":{ "points":[ {"t ...

How to eliminate the scroll bounce effect on iOS using Ionic 3

Currently working on a mobile app that combines elements of both iOS and Android, using ionic-3. Encountering an issue where the scrolling behavior differs between Android and iOS. On Android, scrolling stops when reaching the bottom of the page. However, ...

Angular Error TS2554: Received x arguments instead of the expected 0 on piped operators

I encountered an issue with Error TS2554: Expected 0 arguments, but got 4 when dealing with the observable getHappyDays(). The getHappyDays() Observable returns either Observable<HttpResponse<IHappyDays>> or Observable<HttpErrorResponse> ...

Looking to access XML file data using Vue.js on the server side?

I am trying to access an XML file located in a specific path on the server side using VueJS without using jQuery. Can you provide me with some ideas or advice? Scenario: 1. The file is stored at /static/label/custom-label.xml. 2. I need to read this file ...

Choose an option with JavaScript once the request is successful

Choose the day, month, and year using JSON data success: function(jsondata){ var data=JSON.parse(jsondata); var list_html="<div id='editrelation'><label id='dateLabel' style='display:none&apo ...

How to transition from using a CDN to NPM for implementing the Google Maps JavaScript MarkerClusterer?

Currently integrating Google Maps JavaScript MarkerClusterer from CDN, I am considering transitioning to the NPM version for Typescript checking in my JavaScript files. However, I am encountering difficulties understanding how to make this switch. The docu ...

Using a variable as a parameter when requesting a value from a JSON object in JavaScript

I consider myself to be at an intermediate level in JavaScript, but I've hit a roadblock when trying to access the key in a JSON message that is returned to me. My code is dynamic, so I need to pass the key into the query. For example: After running ...

AngularJs is not responsive to sending POST requests with hidden <input> values

Within my web application, there are multiple forms on a single page. I am looking to utilize AngularJS to submit a specific form. Each form requires a unique ID with a hidden value for submission. However, using value="UNIQUE_ID" in a hidden input field ...

Dynamic content for tooltips in Angular

Currently, I am facing a challenge where I need to dynamically populate content in a tooltip by executing a function with a parameter. This parameter holds the crucial information required to update the tooltip content. The complexity arises from the fact ...