0

I am getting error of Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.

This makes sense, if returning a promise to ensure it resolves, but I really thought that I do that already (by using the await keyword). There seems to be a race condition here that I don't understand

I am writing unit test for a database connection module:

states.js

const sqlite3 = require('sqlite3').verbose();
const util = require('util');

async function getDB() {
    return new Promise(function(resolve, reject) {
        let db = new sqlite3.Database('./project.db', (err) => {
          if (err) {
            console.error(err.message);
                reject(err)
          } else {
            console.log('Connected to the project database.');
                resolve(db)
        }
        });
        return db
    });
}

exports.getDB = getDB

try {
        // run these statements once to set up the db
        // let db = getDB();
        // db.run(`CREATE TABLE services(id INTEGER PRIMARY KEY, service text, date text)`);
        // db.run(`INSERT INTO services(id, service, date) VALUES (1, 'blah', '01-23-1987')`)
} catch(err) {
    console.log(err)
}


exports.get = async function(service) {
     function getResults(service) {
     return new Promise(async function (resolve, reject) {
                const db = await getDB();
                let sql = `SELECT Id id,
                               Service service,
                                                Date date
                        FROM services
                        WHERE service  = ?`;
                 db.get(sql, [service], (err, row) => {
                    if (err) {
                     console.error(err.message);
                     reject(err)
                 } else {
                     if (row) {
                         let this_row = {'id': row.id, 'service': row.service, 'date': row.date};
                         this_row ? console.log(row.id, row.service, row.date) : console.log(`No service found with the name ${service}`);
                         resolve(this_row)
                     } else {
                         resolve(null)
                     }
                 }
                })
     });
  }
    let row = await getResults(service)
    return row
}

exports.clear = async function(service) {
    function deleteResults(service) {
        return new Promise(async function (resolve, reject) {
             const db = await getDB();
             let sql = `DELETE from services
                                  WHERE service  = ?`;
                db.run(sql, [service]);
        });
    }
    await deleteResults(service)
}

my testStates.js:

const mocha = require('mocha');

const assert = require('assert');
const expect = require('chai').expect;
const should = require('chai').should();

const state = require('../state');

let deletion_sql = `DELETE from services WHERE service  = ?`;


it("get() should return the expected row", async function() {
    let db = await state.getDB()
    await db.run(deletion_sql, 'blah')
    await db.run(`INSERT INTO services(id, service, date) VALUES (1, 'blah', '01-23-1987')`)
    let result = await state.get('blah')
    console.log("get test result is")
    console.log(result)
    assert.deepEqual(result, { 'id': 1, 'service': 'blah', 'date': '01-23-1987' })
});


it("clear() should delete row from db", async function() {
  await state.clear('blah')
  let result = await state.get('blah')
  assert.equal(result, null)
})

The test clear() should delete row fromdb` fails every time with the same error, it has not passed once. There is something fundamentally wrong with how I use these promises since I'm new to learning about promise in JavaScript.

halfer
  • 19,824
  • 17
  • 99
  • 186
codyc4321
  • 9,014
  • 22
  • 92
  • 165
  • 1
    `done` is a function that gets passed as an argument to your function it isn't part of the Promise object. You have to call it yourself or set it as one of the Promise's callbacks, eg `.then(done)` / `.finally(done)` – Patrick Evans May 16 '19 at 17:18
  • I don't understand. can you give an example please – codyc4321 May 16 '19 at 17:21
  • I see here you give .then a success callback and possibly error callback, here I give it one so just the success callback https://stackoverflow.com/questions/5436327/jquery-deferreds-and-promises-then-vs-done – codyc4321 May 16 '19 at 17:22
  • 1
    Also you are passing async functions to your `new Promise` calls. When using async functions you don't need to construct a Promise just return the result of executing your async function – Patrick Evans May 16 '19 at 17:25
  • ok thank you i will refactor – codyc4321 May 16 '19 at 17:37

1 Answers1

0

I was able to get test running by using .then() instead of the await keyword:

it("clear() should delete row from db", async function() {
  state.clear('blah').then(async function() {
    let result = await state.get('blah')
    assert.equal(result, null)
  })
})

I am interested to find out why the await keyword didn't work here, since it worked in the other test; I would gladly accept that as answer.

halfer
  • 19,824
  • 17
  • 99
  • 186
codyc4321
  • 9,014
  • 22
  • 92
  • 165