1
votes

I have been trying to resolve these unhandled Promise rejections that I continue to get in my code.

The current one I get is as follows:

[nodemon] starting mocha --recursive -R min (node:35286) UnhandledPromiseRejectionWarning: AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value:

assert(count + 1 === newCount)

at Driver.count.then.newCount (/Users/danale/Projects/muber/test/controllers/drivers_controller.test.js:16:13)
at processTicksAndRejections (internal/process/next_tick.js:81:5) (node:35286) UnhandledPromiseRejectionWarning: Unhandled promise

rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1) (node:35286) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

The test that should be passing is this one:

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

const Driver = mongoose.model("driver");

describe("Drivers controller", () => {
  it("Post to /api/drivers create a new driver", done => {
    Driver.count().then(count => {
      request(app)
        .post("api/drivers")
        .send({ email: "[email protected]" })
        .end(() => {
          Driver.count().then(newCount => {
            assert(count + 1 === newCount);
            done();
          });
        });
    });
  });
});

To deal with the Promise rejections that I was getting earlier I did this:

const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const routes = require("./routes/routes");
const app = express();

mongoose.Promise = global.Promise;
mongoose.connect("mongodb://localhost/muber", { useMongoClient: true });

app.use(bodyParser.json());
routes(app);

module.exports = app;

The controller I am trying to test is:

const Driver = require("../models/driver");

module.exports = {
  greeting(req, res) {
    res.send({ hi: "there" });
  },

  create(req, res) {
    console.log(req.body);
    const driverProps = req.body;

    Driver.create(driverProps).then(driver => res.send(driver));
  }
};

I did try to add the catch() to the test like so:

describe("Drivers controller", () => {
  it("Post to /api/drivers create a new driver", done => {
    Driver.count()
      .then(count => {
        request(app)
          .post("api/drivers")
          .send({ email: "[email protected]" })
          .end((err, res) => {
            Driver.count().then(newCount => {
              assert(count + 1 === newCount);
              done();
            });
          });
      })
      .catch(error => console.log(error));
  });
});

but it did not resolve the error.

This is my route handler:

const DriversController = require("../controllers/drivers_controller");

module.exports = app => {
  // Watch for incoming requests of method GET to the route http://localhost:3050/api
  app.get("/api", DriversController.greeting);

  app.post("/api/drivers", DriversController.create);
};
3
Did you try to catch the example and log it in test case? - Doğancan Arabacı
@DoğancanArabacı, yes I did, I posted how I added the catch() above. - Daniel

3 Answers

0
votes

If you chain your promises properly, you will be able to catch the error:

describe("Drivers controller", () => {
    it("Post to /api/drivers create a new driver", () => {
        let oldCount;
        return Driver.count()
            .then(count => {
                oldCount = count;
                return new Promise((resolve, reject) => {
                    request(app)
                        .post("api/drivers")
                        .send({ email: "[email protected]" })
                        .end((err, res) => {
                            if (err) {
                                reject(err);
                            } else {
                                resolve(res);
                            }
                        });
                });
            }).then(() => {
                return Driver.count();
            }).then(newCount => {
                assert(oldCount + 1 === newCount);
            });
    });
});

In your example, you had promises inside promises, but didn't return/await for these. If the assert statement throws an error, the error will not be forwarded to the outer promise.

0
votes

I might be wrong, but you're doing an comparison and a calculation without doing the count + 1 first. What might fix it is:

assert((count + 1) === newCount)

So in the example above you split the calculation from comparing the values.

See the comment on this below

0
votes

To make it clear for future readers who may run into this problem, when there is an error/incorrect assertion in a Mocha test, an error is raised inside the promise: For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves

After refactoring according to corschdi, I added the solution in link, this bypasses the error about the done() callback and takes you straight to the heart of the problem which is that the asynchronous test is indeed failing.