Ways to verify that express middleware triggers an error when calling next(error)

I attempted to capture the error by using next() when stubbing it, but unfortunately it did not work.

Below is the function:

async getUser (req, res, next) {
  try {
    if (!req.user) {
      throw new CustomError('User not found', 404)
    } else {
      // do something
    }
  } catch (err) {
    next(err)
  }
}

And here is the unit test section:

it('no user data => Error 404', async () => {
  const res = mockedResponse()
  const next = sinon.stub()
  await getUser({}, res, next)
  expect(next.getCall(0).args[0]).to.deep.equal(new CustomError('cannnot find user', 404))
})

However, the test result displays:

AssertionError: expected [Error: cannnot find user] to deeply equal [Error: cannnot find user]

Is there a more effective way to handle the CustomError thrown by the function?

Answer №1

deep-eql algorithm does not perform deep equality checks on errors. For more information, visit this link.

To address this issue, here is the proposed solution:

index.js:

const CustomError = require('./customError');

const controller = {
  async getUser(req, res, next) {
    try {
      if (!req.user) {
        throw new CustomError('User not found', 404);
      } else {
        // perform actions
      }
    } catch (err) {
      next(err);
    }
  },
};

module.exports = controller;

customError.js:

class CustomError extends Error {
  constructor(message, code) {
    super(message);
    this.code = code;
  }
}

module.exports = CustomError;

index.test.js:

const controller = require('./');
const CustomError = require('./customError');
const sinon = require('sinon');
const { expect } = require('chai');

describe('61879445', () => {
  it('should throw error if user not found', async () => {
    const mNext = sinon.stub();
    const mReq = {};
    const mRes = {};
    await controller.getUser(mReq, mRes, mNext);
    
    // Using Chai assertions
    expect(mNext.getCall(0).args[0]).to.be.an.instanceof(CustomError);
    expect(mNext.getCall(0).args[0]).to.have.property('message', 'User not found');
    expect(mNext.getCall(0).args[0]).to.have.property('code', 404);
    
    // Using Sinon assertions
    sinon.assert.calledWith(
      mNext,
      sinon.match
        .instanceOf(CustomError)
        .and(sinon.match.has('message', 'User not found'))
        .and(sinon.match.has('code', 404)),
    );
  });
});

Unit test results along with coverage report:

  61879445
    ✓ should throw error if user not found


  1 passing (15ms)

----------------|---------|----------|---------|---------|-------------------
File            | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------------|---------|----------|---------|---------|-------------------
All files       |     100 |       50 |     100 |     100 |                   
 customError.js |     100 |      100 |     100 |     100 |                   
 index.js       |     100 |       50 |     100 |     100 | 6                 
----------------|---------|----------|---------|---------|-------------------

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

Invoke a fresh constructor within a $get method in Angular's provider

I'm encountering an issue where I am attempting to utilize a function as a constructor inside the `.provider`, but I'm unable to instantiate a new constructor when it's within the `$get`. Here is my provider setup - this.$get = $get; ...

In order to locate where an object intersects with an array

I am new to the world of javascript. Can someone help me understand how to determine the intersection between an array and object in javascript? Consider the following: var users = [{name:'jony'}, {name: 'raja'}, {name: 'papy ...

Tips for testing a component that utilizes an observable service

Seeking guidance on unit testing a function that is listening to an observable service. Feeling a bit lost on where to begin. Below is the component function I want to write unit tests for: register() { this._registrationService.registerUser(this.f ...

When throwing a custom error class, the result is an instance of the Error class instead of the intended custom

I have defined specific error classes such as NotFoundError, ConflictError, and UnauthorizedError. All of these classes extend the BaseError class, which itself is an extension of Nodejs' Error class. When I throw one of my custom errors, I expect th ...

Handling Errors in Express.js for HTTP Requests

What is the best approach for handling errors in http requests? Instead of returning the full error to the client, how can we log the error and send back a message saying Fatal error to the client? Express version: 4.4.4 var express = require('expr ...

Utilizing the dollar shorthand for jQuery in conjunction with Selenium

While utilizing the Selenium addon along with jQuery in my project, I encountered an issue where the use of jQuery functions containing $ in Selenium would trigger a "function not found" error. The problem was resolved by removing jQuery, but using jQuer ...

Utilizing Cascading Templates with mustache-express

My plan is to create a page layout template and a form template. In the route handler, I intended to parse the inner form template and inject it into the main layout before returning it. After encountering several unexpected turns, I managed to utilize th ...

Update the link to a KML file used by Google Maps when a button is clicked

On the initial page load, I want to showcase an 8 Day Average KML file on Google Maps. However, users should have the option to click on the "1 Day" and "3 Day" buttons to switch the reference in Google Maps from the "8 Day" file. The aim is to design a s ...

Unable to trigger click event on dynamically added element using Chrome (jQuery)

My approach here involves dynamically creating a drop-down and binding the click event to the <option> within the <select> var $select = $('<select></select>'), $option1 = $('<option>a</option>') ...

Forward users according to "?ref=XXX" at the end of the URL

I've been searching high and low without success for JavaScript code that can handle the following situation: When visitors arrive at http://example.com, I don't want any action to be taken. However, if they enter through a URL like http://exam ...

Having trouble with filtering an array using the some() method of another array?

When utilizing the code below, my goal is to filter the first array by checking if the item's id exists in the second array. However, I am encountering an issue where the result is coming back empty. dialogRef.afterClosed().subscribe((airlines: Airli ...

"Swap out div content based on chosen dropdown option with the help of Jquery

I am trying to update the languages within my div based on the country I select. Here's what I have attempted so far, but it doesn't seem to be functioning correctly. I have included a link to my fiddle in the comments since I can't paste i ...

Ensuring that form submissions originate from a specific URL requirement in Laravel and iframe integration

My current project involves creating a service that allows users to submit a form via an iframe on their own website. The challenge is ensuring that the form can only be submitted from the domain listed in their User model. I am aware that this is achieva ...

the div's width isn't getting larger

Check out my code snippet: <script> var change = function(){ alert("sam"); for(var i; i >=200; i++){ var z = String(i); var x= document.getElementById("div1"); x.style.width = z; } }; </script> < ...

Store the value returned by the function(data) from the $.post method in a variable

Hello Fellow Developers! I'm currently working on a coding project with the following objective: My goal is to extract URLs of files stored in a specific folder and then store them in an array using JavaScript. Here's how I envision the proces ...

JQuery UI autocomplete vanishes instantly without any warning

I am encountering an issue with JQuery UI's autocomplete feature where the dropdown results do not stay visible. While debugging, I noticed that the list briefly appears before disappearing. Below is my code snippet: HTML: <input type="text" plac ...

Tips for transferring Json data through Ajax in jquery for an html element?

I am facing an issue while trying to display data from 5 rows of a MySQL database in a table using the success function of a jQuery AJAX call. The data is returned in JSON format. Problem: I am able to retrieve only one row at a time, even though the cons ...

Discovering the geographical location of all users using Node.js: A step-by-step guide

My current task involves determining the geoip location of users. I have implemented a code that stores the user's address in the database and then displays the geoip location accordingly. However, if a user changes their location and logs in from a d ...

Is there a way for me to intercept JavaScript code before it runs on Chrome?

Looking to develop a Chrome extension for the developer tools that can intercept JavaScript code on a current web page prior to compilation or execution by the browser. I aim to instrument the JS code before it runs in the browser. Could someone assist wi ...

Using recycled frame buffers in a threejs fragment shader

I'm currently working on a project to develop an app that emulates the effect of long exposure photography. The concept involves capturing the current frame from the webcam and overlaying it onto a canvas. As time progresses, the image will gradually ...