Search code examples
node.jsasync-awaitmocha.jsnode-mssql

node-mssql "connection is closed" when running Mocha test, but runs fine in app


I have a node.js data processing app that pulls some data from mssql. It runs fine and produces the expected results. However, the integration tests aren't working and I would like them to.

Below is the connection management and a test query function. I can see from output and running in the debugger that the test has run and failed before the database has connected. So it seems like my Mocha async setup isn't working, but it looks like everything I've seen in documentation.

node -v v10.15.0

chai: "^4.2.0", mocha: "^5.2.0" mssql: "^4.3.0",

const config = require('./config')
const _ = require('underscore')
const sql = require('mssql')

sql.on('error', err => {
    console.error('SQL Error', err)
})

let api = {}

api.connect = async dbConfig => {
    return new sql.ConnectionPool(dbConfig).connect(
        err => {
            if (err)
                console.error('Connection error', err)
            else
                console.log('connected')
        })
}

var connecting = api.connect(config.sql)

api.simple = async () => {
    let pool = await connecting
    let result = await pool.request().query('select 1 as number')
    return result.recordset[0].number
}

module.exports = api

Here is my mocha test for it that fails

const { expect } = require('chai')
const data = require('../src/data')

describe('data access', function () {

    it('is simple', async function () {
        const yo = await data.simple()
        expect(yo).to.exist
        expect(yo).to.equal(1)
    })
})

I've also tried the older style of async mocha tests using done callbacks ala

it('is simple oldschool',  function (done) {
         data.simple()
        .then(function(yo){
            expect(yo).to.exist
            expect(yo).to.equal(1)
            done()
        })
    })

That times out no matter how long I set Mocha's timeout for (I tried as high as 60 seconds)

I'm at my wits end here, anyone see anything wrong?


Solution

  • api.connect can return before the connection is actually done. Rewriting it like this will make sure ConnectionPool.connect can finish before the api.connect promise resolves.

    api.connect = dbConfig =>
      new Promise((resolve, reject) => {
        const pool = new sql.ConnectionPool(dbConfig);
        pool.connect(err => {
          if (err) {
            console.error("Connection error", err);
            return reject(err);
          }
          return resolve(pool);
        });
      });
    
    

    Beyond that, I'm confused about let pool = await c3; there's no symbol c3 in the code you've pasted...