Anubhav Srivastava
Anubhav Srivastava

Reputation: 229

Why does the await call for my custom promise hang?

I am trying to test a function in my Express/Node backend using Mocha. I have created a stub of the actual parameter which is modified by the function: it has a send method which is called in getValue (the function I want to test) and a ready parameter which I initialize to a new promise when the stub is created and resolve when send is called on the stub.

I'm trying to await this promise, but it's just hanging (and then Mocha times out the test). The setTimeout below prints Promise { 'abc' }, which I think means the promise has resolved as I expect it to, but the await never completes.

This is the relevant code in the test file:

function ResStubTemplate() {
        return {
                _json: undefined,
                _message: undefined,
                json: function(x) {
                        this._json = x;
                        return this;
                },
                send: function(message) {
                        this._message = message;
                        this.ready = Promise.resolve("abc");
                        return this;
                },
                ready: new Promise(_ => {})
        }
}

// This is the test
it("should get the value.", async function(done) {
        let req = { query: { groupId: 12345 } };
        res = ResStubTemplate();
        controller.getValue(req, res);
        setTimeout(() => console.log(res.ready), 1000); // prints Promise { 'abc' }
        let x = await res.ready; // hangs??
        console.log(x); // never prints
        done();
}

This is the relevant code in the tested file:

exports.getValue = function(req, res) {
        ValueModel.findOne({groupId: req.query.groupId})
           .then(value => res.json({value: value}).send();                                                                                                         
};                                                                                                    

The error I get is:

Error: Timeout of 5000ms exceeded. 
For async tests and hooks, ensure "done()" is called; if returning a Promise,
ensure it resolves. (/.../test/api/controller_test.js)

Upvotes: 1

Views: 2162

Answers (1)

Quentin
Quentin

Reputation: 944202

When the expression:

let x = await res.ready; // hangs??

… is evaluated, the value is the promise created by this code:

ready: new Promise(_ => {})

That promise never resolves, so it keeps waiting for it.

Later you do this:

 this.ready = Promise.resolve("abc");

… which replaces that promise with a new (resolved) promise, but the new promise isn't the value that you are awaiting.

Upvotes: 4

Related Questions