Как провести модульное тестирование соединения с пулом?

Я хотел бы провести модульное тестирование (mocha & chai) соединения пула (mysql) в моем приложении node.js. Я не знаю, правильно ли я использую тесты, и если да, то почему они всегда считаются «ожидающими».

Дав следующий код, как мне его протестировать?

var pool = mysql.createPool({
    connectionLimit: 100,
    host: 'localhost',
    user: 'userName',
    password: 'userPass',
    database: 'userDatabase',
    debug: false
});

Я пробовал разными способами, но, похоже, это не сработало. Лучшее, что у меня получилось, было это:

describe("Database", function () {
    describe("Connection", function () {
        it("Should connect without an error", pool.getConnection(function (err, connection) {
            expect(err).to.be.null;
            })
        );
    })
});

Что вернется, если учетные данные верны:

Express server listening on port 8080
  Database
    Connection
      - Should connect without an error


  0 passing (15ms)
  1 pending

И вернемся, если учетные данные неверны:

Express server listening on port 8080
  Database
    Connection
      - Should connect without an error
      1) Uncaught error outside test suite


  0 passing (23ms)
  1 pending
  1 failing

  1) Database Connection Uncaught error outside test suite:
     Uncaught AssertionError: expected [Error: ER_DBACCESS_DENIED_ERROR: Access denied for user 'userName'@'localhost' to database 'userDatabase'] to be null

Заранее спасибо.


person Faegy    schedule 24.02.2017    source источник
comment
Обратите внимание, что это интеграционный тест, а не модульный тест. Он проверяет, что две системы работают вместе, а не одна функциональная единица в вашем приложении, которая работает хорошо сама по себе. См. stackoverflow.com / questions / 1217736 / для тестирования вызовов базы данных.   -  person Liam Gray    schedule 24.02.2017


Ответы (2)


То, что вы передаете it во втором аргументе, должно быть функцией. Прямо сейчас вы делаете:

it("Should connect without an error", pool.getConnection(...))

pool.getConnection принимает обратный вызов, поэтому, по всей вероятности, он возвращает undefined. Для Мокко это выглядит так:

it("Should connect without an error", undefined)

И это ожидающий тест, потому что наличие undefined для обратного вызова - это способ сообщить Mocha, что тест ожидает завершения. Вам нужно обернуть ваш вызов pool.getConnection в функцию:

it("Should connect without an error", function (done) {
    pool.getConnection(function (err, connection) {
        if (err) {
            done(err); // Mocha will report the error passed here.
            return;
        }
        // Any possible tests on `connection` go here...

        done();
    });
});
person Louis    schedule 24.02.2017
comment
Если expect(err).to.be.null вызывает исключение, done() не будет вызываться, и, следовательно, тест не разрешится, пока не истечет время ожидания? - person Liam Gray; 24.02.2017
comment
Это правда, но в целом это не проблема. В 99,9999% случаев тест проходит, и таймаут не срабатывает. Тем не менее я отредактировал свой ответ, чтобы показать, как его можно сразу передать. Если OP не собирается выполнять какие-либо другие тесты в обратном вызове, OP может уменьшить его до того, что указано в вашем ответе, но если будет выполнено какое-либо тестирование на connection, то сначала следует проверить err. - person Louis; 24.02.2017
comment
Допустим, я использую pool.getConnection() в конструкторе объекта и присваиваю значения из результата запроса своим свойствам объекта, будет ли вызов done() ждать, пока мой объект не будет полностью создан, например, при вызове var user = new User(1);? - person Faegy; 26.02.2017
comment
Вызов done() фактически помечает ваш тест как завершенный , как только происходит вызов. Вы должны отложить звонок done. Если вы заставляете свой конструктор работать асинхронно, проблема, с которой вы сталкиваетесь, одинакова при тестировании и в производственной среде: при тестировании необходимо знать, когда конструктор завершил создание объекта, но производственный код также должен это знать. В противном случае он будет использовать объект слишком рано. В большинстве рекомендаций рекомендуется заставить конструктор работать синхронно, а любые асинхронные операции должны выполняться методами, вызываемыми в экземпляре. - person Louis; 27.02.2017

См. тестирование асинхронного кода в документации mocha. Ваша it функция должна выглядеть примерно так, как показано ниже.

it('Should connect without an error', function (done) {
  pool.getConnection(done);
});

Или, если вы хотите добавить утверждения в свой обратный вызов, сделайте следующее:

it('Should connect without an error', function (done) {
  pool.getConnection((err, connection) => {
    try {
      expect(connection).to.not.be.null;
      expect(connection).to.have.property('foo');
      done();
    } catch (error) {
      done(error);
    }
  });
});

Обратите внимание, что желательно тестировать с помощью обещаний, потому что это позволяет запускать операторы expect для объекта соединения без дополнительных операторов try / catch / done. Например, если pool.getConnection возвращает обещание, вы можете:

it('Should connect without an error', function () {
  return pool.getConnection(connection => {
    expect(connection).to.have.property('foo');
    // more assertions on `connection`
  });
});

Также обратите внимание, что это не «модульные тесты», а интеграционные тесты, поскольку они проверяют совместную работу двух систем, а не только поведение вашего приложения, как ожидалось, по отдельности.

person Liam Gray    schedule 24.02.2017