соединение node-mssql закрывается при запуске теста Mocha, но отлично работает в приложении

У меня есть приложение для обработки данных node.js, которое извлекает некоторые данные из mssql. Он работает нормально и дает ожидаемые результаты. Однако интеграционные тесты не работают, и я бы хотел, чтобы они работали.

Ниже приведено управление подключением и функция тестового запроса. Я вижу из вывода и работы в отладчике, что тест был запущен и не прошел до того, как база данных подключилась. Итак, похоже, что моя асинхронная установка Mocha не работает, но похоже на все, что я видел в документации.

узел -v v10.15.0

чай: "^4.2.0", мокко: "^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

Вот мой тест мокко, который не проходит

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)
    })
})

Я также пробовал старый стиль асинхронных мокко-тестов с использованием готовых обратных вызовов аля

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

Это время истекает независимо от того, как долго я устанавливаю тайм-аут Mocha (я пробовал до 60 секунд)

Я в своем уме здесь, кто-нибудь видит что-то не так?


person µBio    schedule 25.01.2019    source источник


Ответы (2)


api.connect может вернуться до того, как соединение будет установлено. Переписав его таким образом, мы удостоверимся, что ConnectionPool.connect может завершиться до того, как будет разрешено обещание api.connect.

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);
    });
  });

Кроме того, я запутался насчет let pool = await c3; в коде, который вы вставили, нет символа c3...

person AKX    schedule 25.01.2019
comment
упс, переименовал с3 на правильное имя. Просто опечатка при очистке для публикации. Исправлен мой вопрос - person µBio; 25.01.2019
comment
с одним небольшим изменением (вернуть обещание из функции api.connect :)), это работает. Если вы не возражаете, немного поясните, почему асинхронное выполнение api.connect и ожидание api.connect(config.sql) не ведут себя одинаково? - person µBio; 25.01.2019
comment
Потому что вы не сделали await для завершения pool.connect (и вы, в любом случае, не можете, так как это функция на основе обратного вызова, а не на основе обещаний). Мой ответ более или менее просто шаблонный способ обещать функцию на основе обратного вызова. :) - person AKX; 25.01.2019
comment
Кроме того, я должен отметить, что это, вероятно, была чистая удача, что это работало в вашем приложении раньше! Итак, вы только что исправили будущую ошибку! - person AKX; 25.01.2019
comment
Ха-ха, спасибо за помощь и объяснение ... Я подозреваю, что остальная часть приложения запустилась достаточно долго, поэтому до завершения соединения не было выполнено ни одного вызова базы данных. - person µBio; 25.01.2019

Я думаю, что у вас есть состояние гонки с подключением к базе данных.

Я делаю это раньше()

before((done) => {
    server.on("serverStarted", function() {
         done();
    });
});

Затем на моем сервере (я использую узел) я испускаю, когда я подключен:

var port = process.env.PORT || 3030;
var server = http.listen(port, function(){
    console.log('listening on port: ' + port);
    db.connect().then(() => {
        console.log("Connect to database successful");
        server.emit("serverStarted") // HERE IT IS
    }).catch(err => {
        console.error(err);
        console.log("Cannot connect to database");
        process.exit(1);
    });
});

Надеюсь это поможет. Я вырвал некоторые волосы на этом.

person Matt Kuhns    schedule 25.01.2019
comment
Спасибо за ответ. В моем случае это не веб-приложение, это приложение для фоновой обработки. Я начал изучать генерацию события для обработки в before(), но ответ @AKX чище. - person µBio; 25.01.2019