1

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: "test@test.com" })
        .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: "test@test.com" })
          .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);
};
Daniel
  • 14,004
  • 16
  • 96
  • 156

3 Answers3

0

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

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: "test@test.com" })
                        .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.

Carsten
  • 905
  • 6
  • 7
  • with your solution I still get a failing test: `Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.` – Daniel May 27 '19 at 15:12
  • you brought me the closest to the answer which lead me to this answer: https://stackoverflow.com/questions/44149096/for-async-tests-and-hooks-ensure-done-is-called-if-returning-a-promise-en, it helps in resolving the Promise when testing and this answer also helps me understand that the test is the issue. – Daniel May 27 '19 at 15:17
  • I have updated the code to resolve that problem by returning a promise to Mocha. If any exception occurs, mocha should actually fail the test. That's why you don't need a catch clause anymore. – Carsten May 27 '19 at 15:27
  • your earlier solution worked. This one gives me a Connection Refused. The test is indeed failing, thank you for that earlier solution, I would put that one back so it can help others. – Daniel May 27 '19 at 15:29
  • Isn't the test supposed to fail if the request to `api/drivers` results in a `Connection Refused` error? – Carsten May 27 '19 at 15:34
  • Well, any of the `then` functions could be an error source. You can only be sure about that if you debug your test or add additional assert statements before the failing statements (like checking the connection). Since you want to test your controller, you should make sure that everything is set up properly before running the test. Failed tests should only be caused by assert statements. – Carsten May 27 '19 at 15:45
  • I checked for database existence in Mongo and sure enough its not there and I am not 100% confident in my database connection configuration as a lot has changed with mongoose since I last used it. – Daniel May 27 '19 at 15:46
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/194012/discussion-between-daniel-and-corschdi). – Daniel May 27 '19 at 15:50
0

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.

Daniel
  • 14,004
  • 16
  • 96
  • 156