Search code examples
node.jsexpressjestjssupertest

Request timeout using jest, supertest to test for a wrong URL error or mongodb database ValidationError on an express server that has an error handler


I am running a test that never returns the error till the test times out, however this works pretty well with postman or insomnia

index.js

const express = require("express");
const app = express();

app.get("/", function(req, res, next) {
  // explicitly return an error
  return next("my error");
});

app.use(function(error, req, res, next) {
  if (error) {
   res.status(500).send({ error });
    throw new Error(error); // <- how to test this?
  }
  next();
});

app.listen(8080, function() {
  console.log("server running on 8080");
}); //the server object listens on port 8080

index.test.js

const request = require("supertest");
const app = require("../../app.js");

const spy = jest.spyOn(global.console,"error").mockImplementation();

it("throws an error", async done => {
  const res = await request(app).get("/");

  expect(res.status).toBe(500);
  expect(res.error.text).toContain("my error");

  // nothing...
  expect(spy).toHaveBeenCalled();

  done();
});

Solution

  • Been a while since I used jest but, as far as I remember, the only way to test for errors I think is to add a try/catch block around the await request(app).get('/') and write the expects in the catch block. You can also play around with the error object e to verify other things you want to about the error such as the error message that you might be throwing.

    const request = require("supertest");
    const app = require("../../app.js");
    
    const spy = jest.spyOn(global.console,"error").mockImplementation();
    
    it("throws an error", async done => {
      let res;
      try {
        res = await request(app).get("/");
      } catch (e) {
        expect(e).toBeInstanceOf(HTTP422Error)
        // Replace HTTP422Error with whatever error you are throwing or just `Error` is fine too
      }
      expect(res.status).toBe(500);
      expect(res.error.text).toContain("my error");
    
      // nothing...
      expect(spy).toHaveBeenCalled();
    
      done();
    });