Тестирование promise с помощью mocha

В своём «домашнем» проекте для тестирования кода я использую фреймворк mocha. В тестах все утверждения проверяются библиотекой should.js , которая выбрасывает соответствующие исключения, отлавливаемые mocha.

При тестировании promise -объектов возникла проблема из-за того, что все исключения, выброшенные внутри резолвера, автоматически отлавливаются этим объектом. В результате тесты падают по таймауту без дополнительных разъяснений.


describe("Listener", function () {
    it("should reject data", function (done) {
        var connection = new MockStream();
        var promise = listener(connection);
        connection.write("foo bar baz");
        connection.end();

        promise.then(
            function (obj) {
                done(new Error("unexpected fulfill"));
            },
            function (obj) {
                obj.should.be.a("object").and
                  .have.property("valid", false);
                done();
            }
        );

    });
});

В данном тесте я ожидаю, что promise будет отклонён с объектом, в качестве параметра, имеющим поле valid равное значению false. Если утверждение не будет соответствовать действительности, то тест не завершится естественным образом (т.е. вызов done() , который идет за утверждением, не будет выполнен).

Благо, каждый вызов метода then() возвращает другой promise-объект. Он выполняет или отклоняется так же как и его «предок», но в параметры колбеков будут передаваться совершенно другие значения. Этим можно воспользоваться для корректного завершения теста.


describe("Listener", function () {
    it("should reject data", function (done) {
        var connection = new MockStream();
        var promise = listener(connection);
        connection.write("foo bar baz");
        connection.end();

        promise.then(
            function (obj) {
                // throw new Error("unexpected fulfill");
                return new Error("unexpected fulfill");
            },
            function (obj) {
                obj.should.be.a("object").and
                  .have.property("result", false);
            }
        ).then(done, done);

    });
});

При любом изменении состояния исходного promise-объекта будет вызываться done(). Отличаться будет только параметр, с которым он будет вызван:

  • объект ошибки в случае неверного состояния или выбрасывания исключения;
  • undefined при удачном завершении теста.

Именно такие значения параметра определяют состояние теста в mocha.