devamat
devamat

Reputation: 2513

Jest / NodeJS, how to build a test for "unhandledRejection"

I'm trying to have 100% coverage.

I'm stuck at creating a test for this part of my code:

// Manually throwing the exception will let winston handle the logging
process.on("unhandledRejection", (ex) => {
  throw ex;
});

I tried to use the following:

const logger = require("../../../startup/logging");

describe("startup / logging", () => {
  it("should log the error in case of unhandledRejection", () => {
    process.emit("unhandledRejection");
    const loggerError = jest.spyOn(logger, "error");
    expect(loggerError).toHaveBeenCalled();
  });
});

But the test fails with: thrown: undefined

This is the full code of logging.js:

const { createLogger, format, transports } = require("winston");
require("winston-mongodb");
// This will forward the error in the pipeline to our error handler
require("express-async-errors");

// Manually throwing the exception will let winston handle the logging
process.on("unhandledRejection", (ex) => {
  throw ex;
});

// Log to files
const logger = createLogger({
  format: format.combine(
    format.timestamp({
      format: 'YYYY-MM-DD HH:mm:ss'
    }),
    format.errors({ stack: true }),
    format.splat(),
    format.json()
  ),
  transports: [
    new transports.File({filename: "./logs/combined.log", level: "verbose"}),
  ],
  transports: [
    new transports.File({filename: "./logs/error.log", level: "error"}),
    new transports.File({filename: "./logs/combined.log"}),
  ],
  exceptionHandlers: [
    new transports.File({ filename: "./logs/exceptions.log" }),
    new transports.File({ filename: "./logs/combined.log" }),
  ],
  handleExceptions: true,
});

// Log to database
logger.add(new transports.MongoDB({
  level: "error",
  db: "mongodb://localhost:27017/rest-api-mongodb",
  options: {
    useUnifiedTopology: true,
    useNewUrlParser: true,
  },
  metaKey: "stack",
  handleExceptions: true,
}));

module.exports = logger;

This is the error middleware that is triggered in case of unhandledRejection:

// Winston is a logger, it allows to store errors in a log and mongoDB
const logger = require("../startup/logging");

// This function will handle all errors in the router
// It works thanks to require("express-async-errors"); that forwards the error in the pipeline

// It does not work outside of the context of express
module.exports = function (err, req, res, next) {
  logger.error(err.message, err);
  // error, warn, info, berbose, debug, silly
  res.status(500).send("Something on the server failed.");
}

Any help is appreciated!

Upvotes: 3

Views: 1347

Answers (2)

devamat
devamat

Reputation: 2513

After playing around with the code, I made it work as follows:

require("../../../startup/logging");

describe("startup / logging", () => {
  it("should throw an error if there is an unhandledRejection", () => {
    const emitUnhandledRejection = () => process.emit("unhandledRejection");
    expect(emitUnhandledRejection).toThrow();
  });
});

Upvotes: 2

snek
snek

Reputation: 2161

Try triggering unhandledRejection by using a real unhandled rejection. For example, call Promise.reject() without attaching a handler.

Upvotes: 2

Related Questions