Jest: Promise tests keep running

Created on 6 Apr 2017  路  6Comments  路  Source: facebook/jest

Introduction

As part of an integration test with a database handled by mysqljs we are trying to test the connection as a Promise. Those tests were previously successfully handled by mocha. Now that we've switched to jest, a testing issue occurs that prevents the global testing process to finish. It may be important to underline the fact that I'm only new to javascript for 3 months and, however I strongly believe it isn't (see Work-around), this may be an error rather than a bug.

Desired outcome

Run all tests and show the results when done.

Current outcome

All tests shown as ran but the global process still shows "Running tests...".

Reproduce

Modules

While facing this issue, the following dependencies were installed on Nodejs:

"dependencies": {
    "body-parser": "~1.16.0",
    "cookie-parser": "~1.4.3",
    "debug": "~2.6.0",
    "express": "~4.14.1",
    "morgan": "~1.7.0",
    "mysql": "^2.13.0",
    "pug": "~2.0.0-beta10",
    "serve-favicon": "~2.3.2",
    "vhost": "^3.0.2"
},
"devDependencies": {
    "jest": "^19.0.2",
    "jest-cli": "19.0.2"
}

Code

Database.js

var mysql = require('mysql');
var pool  = mysql.createPool({
    connectionLimit : 100,
    host            : 'localhost',
    user            : 'user',
    password        : 'password',
    database        : 'database'
});
module.exports = pool;

Database.test.js

const Pool = require('../lib/Database');
describe("Connection", ()=>{
    it('Should connect without an error', ()=>{
        return new Promise(function (resolve, reject) {
            Pool.getConnection((error, connection)=>{
                if(error){
                    reject(error);
                    try {
                        connection.release();
                    } catch (e) {

                    }
                }
                connection.query("SELECT * FROM ??", ['User'], (err, result, fields)=>{
                    if(err){
                        reject(err);
                    }
                    try{
                        connection.release();
                    } catch (e) {

                    }
                    resolve(result);
                })
            })
        });
    });
});

Screenshots & work-around

Producing the issue

1. Running the tests as expected - Producing the issue

By running the basic test command all tests are ran but the global process never finishes.
Running the tests as expected

2. Force-stopping the tests - Producing the issue

By force-stopping the execution everything switches to the expected state.
Force-stopping the tests

Work-around

1. Forcing a jest error - Initiating the work-around

This part requires you to force a timeout by (not-)using the done() call-back. This results in an expected error.
Forcing a jest error

2. Re-running all tests - Executing the work-around

Removing the usage of done() gets us back to our initial code that we can re-test. Here all tests are ran as expected with the desired outcome and all suites being executed.
Re-running all tests

End note

Should this be an error of mine, I deeply apologize for wasting your time and would really appreciate it if you could explain where this error is located and how to fix it.

Thank you!

Most helpful comment

Glad I switched to Jest to detect this 馃槃

All 6 comments

Shouldn't you call connection.end() somewhere? E.g. in afterAll() hook.

According to the documentation you only need to call connection.release():

When you are done with a connection, just call connection.release() and the connection will return to the pool, ready to be used again by someone else.

var mysql = require('mysql');
var pool  = mysql.createPool(...);

pool.getConnection(function(err, connection) {
 // Use the connection
 connection.query('SELECT something FROM sometable', function (error, results, fields) {
   // And done with the connection.
   connection.release();

   // Handle error after the release.
   if (error) throw error;

   // Don't use the connection here, it has been returned to the pool.
 });
});

This is being called in my Database.test.js on line 22 within a try/catch block.
I still tried to call connection.end() which doesn't resolve the issue and throws another warning suggesting connection.release() should be used:

Calling conn.end() to release a pooled connection is deprecated. In next version calling conn.end() will be restored to default conn.end() behavior. Use conn.release() instead.

connection.end

It may be interesting to notice that this code was functional with chai-as-promised, that's why I doubt the issue is on mysqljs-es side.

On further investigation, it looks like this only occurs with pooled connections as working with single connection works.

Database.js

var mysql = require('mysql');
var pool  = mysql.createConnection({
    connectionLimit : 100,
    host            : 'localhost',
    user            : 'user',
    password        : 'pass',
    database        : 'db'
});

module.exports = pool;

Database.test.js

const Pool = require('../lib/Database');
describe("Connection", ()=>{
    it('Should connect without an error', ()=>{
        return new Promise(function (resolve, reject) {
            Pool.connect();
            Pool.query("SELECT * FROM ??", ['User'], (error, results, fields)=>{
                if(error) reject(error);
                resolve(results);
            });
            Pool.end();
        });
    });
});

Finally found the issue, it was Pool.end() being required but badly positioned. Weir that it still passed mocha...
All my apologies. This was indeed an error of mine.

It's possible, that mocha's default behaviour is similar to Jest with --forceExit. But as you can see this can lead to leaky tests. Glad you solved the problem 馃檪

Glad I switched to Jest to detect this 馃槃

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rosiakr picture rosiakr  路  3Comments

kgowru picture kgowru  路  3Comments

samzhang111 picture samzhang111  路  3Comments

ianp picture ianp  路  3Comments

jardakotesovec picture jardakotesovec  路  3Comments