Почему эта ошибка, как и было обещано, AssertionError выводится на консоль, а не на мой тестовый запуск Mocha?

Я пытаюсь протестировать код, который использует обещания с chai-as-promised а также Mocha, Мой набор тестов также использует fetch-mock для имитации запросов AJAX, которые обычно отправляются с использованием API Fetch.

Вот код, который я пытаюсь проверить:

/**
 * Sends a POST request to save (either insert or update) the record
 * @param  {object} record simple object of column name to column value mappings
 * @return {Promise}       Resolves when the POST request full response has arrived.
 * Rejects if the POST request's response contains an Authorization error.
 */
save(record) {
  var _this = this;
  return this._auth(record)
    .then(function() {
      return window.fetch(_this._getPostUrl(), {
        method: 'post',
        headers: {
          'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8'
        },
        body: _this._objToPostStr(record),
        credentials: 'include'
      });
    })
    .then(function(saveResp) {
      return saveResp.text();
    })
    .then(function(saveResp) {
      return new Promise(function(resolve, reject) {
        if (saveResp.indexOf('Authorization') !== -1) {
          reject('Request failed');
        } else {
          resolve(saveResp);
        }
      });
    });
}

На моем самом верхнем уровне describeУ меня есть эта функция, которая изначально настраивает мой fetchMock объект.

before(() => {
  fetchMock = new FetchMock({
    theGlobal: window,
    Response: window.Response,
    Headers: window.Headers,
    Blob: window.Blob,
    debug: console.log
  });
  fetchMock.registerRoute({
    name: 'auth',
    matcher: /tlist_child_auth.html/,
    response: {
      body: 'authResp',
      opts: {
        status: 200
      }
    }
  });
});

и вот соответствующий код теста:

describe('save', () => {
  it('save promise should reject if response contains the string Authorization', () => {

    fetchMock.mock({
      routes: ['auth', {
        name: 'save',
        matcher: /changesrecorded.white.html/,
        response: {
          body: 'Authorization',
          opts: {
            status: 200
          }
        }
      }]
    });

    let _getLocationStub = sinon.stub(client, '_getLocation');
    _getLocationStub.returns('/admin/home.html');

    client.foreignKey = 12345;
    let promise = client.save({
      foo: 'bar'
    });
    promise.should.eventually.be.fulfilled;
    fetchMock.unregisterRoute('save');
  });
});

Причина, по которой я определяю save маршрут в fetchMock.mock() вызов у ​​меня есть еще один тест, который нуждается в save маршрут, который будет переопределен, чтобы вернуть что-то еще.

Чтобы убедиться, что Chai-as-обещано действительно работает и будет уведомлять меня о неудачных тестах, я написал неудачный тест promise.should.eventually.be.fulfilled;, Это не удастся, потому что обещание возвращается save будет отклонен, если ответ содержит Authorization, который это делает. Консоль Chrome отображает ошибку AssertionError с message: expected promise to be fulfilled but it was rejected with 'Request failedно мой мокко test-runner.html страница показывает, что этот тест пройден. По какой-то причине Чаи-как-обещал не общается должным образом с Мокко.

Если вы хотите увидеть весь мой проект, пожалуйста, посмотрите этот репозиторий на Github.

Есть идеи почему?

РЕДАКТИРОВАТЬ:

Вот мой код установки теста:

let expect = chai.expect;
mocha.setup('bdd');
chai.should();
chai.use(chaiAsPromised);

1 ответ

Решение

Значение promise.should.eventually.be.fulfilled это обещание, которое вы должны вернуть, чтобы Мокко могло знать, когда ваш тест закончен. Я создал небольшой тестовый файл для имитации того, что вы видели, и я могу полностью повторить поведение, если, как и вы, я просто не могу вернуться promise.should.eventually.be.fulfilled;, Вот пример, который работает:

import chai from "chai";
import chaiAsPromised from "chai-as-promised";

chai.use(chaiAsPromised);
chai.should();

describe("foo", () => {
    it("bar", () => {
        let promise = Promise.reject(new Error());
        return promise.should.eventually.be.fulfilled;
    });
});

В вашем коде у вас был код очистки в самом конце вашего теста: fetchMock.unregisterRoute('save');, Исходя из того, что вы показываете, я бы переместить это в after крючок, чтобы он отражал ваш before крюк. В общем, after следует выполнить очистку, которая соответствует тому, что находится в before а также afterEach к тому, что в beforeEach, Однако если по какой-то причине вам нужен код очистки внутри теста, вы можете сделать:

        function cleanup() {
            console.log("cleanup");
        }

        return promise.should.eventually.be.fulfilled.then(
            // Called if there is no error, ie. if the promise was
            // fullfilled.
            cleanup,
            // Called if there is an error, ie. if the promise was
            // rejected.
            (err) => { cleanup(); if (err) throw err; });

К сожалению, Chai, кажется, возвращает что-то похожее на ES6 Promise но только частично. В конце концов, он, вероятно, вернет фактическое обещание ES6, и тогда вы сможете позвонить .finally запускать код очистки независимо от того, что происходит, и ошибка автоматически распространяется.

Другие вопросы по тегам