Почему эта ошибка, как и было обещано, 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
запускать код очистки независимо от того, что происходит, и ошибка автоматически распространяется.