Синяя птица Каждая петля в мокко не работает
Я пишу тест, в котором мне нужно перебрать результаты асинхронного вызова API и динамически создать мокко "Свой" для проверки каждой итерации ответа. Я нашел несколько других связанных ответов, которые заставили меня начать. Вот что я пробовал до сих пор.
function getter(uri) {
return new Promise(function(resolve, reject) {
request({
method: 'GET',
json: true,
uri: uri
}, function(error, response, body) {
if (response.statusCode == 200) {
resolve(body);
} else {
reject(error);
}
});
});
}
describe('This works', function() {
it('works', function(done) {
getter('myapi_that_returns_an_array').then(function(r) {
r.should.not.be.empty;
done();
}).catch(function(err) {
done(err);
});
});
});
describe('Why not this one', function() {
getter('myapi_that_returns_an_array').each(function(r) {
it('should make a test', function(done) {
r.should.not.be.empty;
done();
});
});
});
Я попытался просто обернуть простой массив в обещание и передать его в мой тест, и это работает! Поэтому я не могу понять, почему вызываемый мной API-интерфейс не работает так же.
function simple_test() {
return new Promise(function (resolve, reject) {
resolve([ [1, 2, 3, 4], [2, 3, 4, 1], [3, 4, 2, 1], [4, 1, 2, 3] ]);
});
}
describe('But this one works', function() {
two().each(function(r) {
it('is a test', function(done) {
r.should.not.be.empty();
done();
});
});
});
Я попытался добавить тайм-аут для simple_test, чтобы он действовал как вызов API - результат такой же, как вызов API. Есть ли способ сделать это с мокко? Похоже, что описание выполняется перед ожиданием разрешения обещания.
2 ответа
Версия вашего теста, которая пытается генерировать тесты, вызывая it
внутри getter.each
не может работать, потому что у Mocha нет условий для генерации тестов асинхронно, что вы пытаетесь сделать. Как я объяснил здесь:
То, что вы получаете, связано с тем, как Мокко обнаруживает ваш тест. В основном Мокко делает это:
Прочитайте все ваши тестовые файлы и выполните их. Обратные вызовы переданы
describe
исполняются сразу. Обратные вызовы переданыit
и до крючков (before, beforeEach
и т. д.) записываются для последующего исполнения.Мокко выполняет то, что записал, для последующего исполнения (согласно некоторому разумному порядку, который здесь не важен).
Проблема с попыткой генерировать тесты асинхронно состоит в том, что к тому времени, когда асинхронный код выполняется, вы выходите из себя. describe
блок, и тесты игнорируются. Нет способа заставить Mocha ждать асинхронную операцию, прежде чем он рассмотрит describe
заблокировать
Я думаю, что проблема в том, что вы должны определять тесты синхронно, хотя каждый отдельный тест может выполняться асинхронно. Вы можете динамически определять it()
блоки из статических данных, потому что эти тесты определены до describe()
звонок возвращается.
Я не до конца понимаю, почему тест работает асинхронно с небольшим или нулевым интервалом ожидания, но мои эксперименты показывают, что it()
должен быть вызван по крайней мере один раз, прежде чем describe()
возвращает тесты, которые будут распознаны в выходных данных. С тайм-аутом в 1 миллисекунду я видел тесты, описанные в родительском блоке.
С помощью before()
блоки страдает от той же проблемы. before()
может дождаться разрешения обещанного массива, но без it()
тесты статически определены, before()
никогда не будет работать
Простая, но нежелательная альтернатива будет иметь один it()
заблокируйте тестирование всех данных, возвращаемых вашим сервисом. Другой вариант - использовать результаты вашего веб-сервиса, чтобы сначала динамически сгенерировать тестовый файл mocha, а затем запустить mocha для него.
var assert = require("assert");
var Promise = require("bluebird");
var testData = [
{ "name": "Test 1", "value": true },
{ "name": "Test 2", "value": false },
{ "name": "Test 3", "value": true }
];
function getTestData(timeout) {
return new Promise(function (resolve, reject) {
if (timeout) {
setTimeout(function () {
resolve(testData);
}, timeout);
} else {
resolve(testData);
}
});
}
describe("Dynamicly Generating Tests", function() {
describe("A: Promised Array, no timeout - Works", function () {
getTestData().each(function (test) {
it("A: " + test.name, function () {
assert.ok(test.value);
});
});
});
describe("B: Promised Array, short timeout - Works?", function () {
getTestData(1).then(function (testData) {
testData.forEach(function (test) {
it("B:" + test.name, function () {
assert.ok(test.value);
});
});
});
});
describe("C: Promised Array, timeout, single it() - Works!", function () {
it("C: Has all correct values", function () {
return getTestData(1000).each(function (test) {
assert.ok(test.value, test.name);
});
})
});
});