Я написал несколько модульных тестов для API, управляемых node.js, который я построил с использованием Jasmine.Тесты Jasmine async внутри цикла работают не так, как ожидалось
Тесты работают нормально, но теперь я хотел бы запустить набор асинхронных тестов с различными входами, но я не могу заставить его работать.
Мои тесты запускают некоторые запросы против API с параметром «смещение» и «ограничение» в URL-адресе, а API вставляет ссылки для разбивки на страницы в ответе (во-первых, предыдущий, следующий и последний).
Вот мой Жасмин тест:
describe('API with "limit" and "offset" parameters', function() {
var offset = 0;
var limit = 4;
var url = baseUrl + '?limit=' + limit + '&offset=' + offset;
beforeEach(function(done) {
request.get(url, function(err, res, resBody) {
response = res;
body = JSON.parse(resBody);
count = body.count;
done();
});
});
it('should respond with status code 200', function(done) {
expect(response.statusCode).toEqual(200);
done();
});
it('should have a response with [limit] results if count - offset >= limit, otherwise count - offset', function(done) {
if(count - offset >= limit) expect(body.rows.length).toEqual(limit);
else expect(body.rows.length).toEqual(count - offset);
done();
});
it('should have navigation links', function(done) {
expect(body.first).toBeDefined();
expect(body.prev).toBeDefined();
expect(body.next).toBeDefined();
expect(body.last).toBeDefined();
done();
});
it('should have "first" navigation link equal to url offset=0 and limit=limit', function(done) {
expect(body.first).toEqual(baseUrl + '?limit=' + limit + '&offset=0');
done();
});
it('should have "prev" navigation link equal to null if offset=0, otherwise offset = offset - limit', function(done) {
if(offset ===0) expect(body.prev).toBeNull();
else expect(body.prev).toEqual(baseUrl + '?limit=' + limit + '&offset=' + (offset - limit));
done();
});
it('should have "next" navigation link equal to offset + limit, or null if offset+limit > count', function(done) {
if(offset + limit <= count) expect(body.next).toEqual(baseUrl + '?limit=' + limit + '&offset=' + (offset + limit));
else expect(body.next).toBeNull();
done();
});
it('should have "last" navigation link equal to floor(count/limit)*limit', function(done) {
expect(body.last).toEqual(baseUrl + '?limit=' + limit + '&offset=' + Math.floor(count/limit) * limit);
done();
});
});
Этот тест работает нормально, но сейчас я хотел бы повторно запустить этот тест, в каждом цикле увеличивающегося «смещение» на «предел», пока последняя страница не будет достигнут (т.е. offset + limit> = count), но я не могу заставить это работать.
То, что я пытался до сих пор
Моя первая идея состояла в том, чтобы поставить тесты внутри цикла, помещенные в IIFE, но это не работает, потому что «счет» в течение петли не определено (Я предполагаю, что это доступно только внутри «это»):
for(var i=offset; i<count; i+=limit) { // "count" is undefined here
(function(offset, count, limit) {
it('should have "first" navigation link equal to url offset=0 and limit=limit', function(done) {
expect(body.first).toEqual(baseUrl + '?limit=' + limit + '&offset=0');
done();
});
it('should have "prev" navigation link equal to null if offset=0, otherwise offset = offset - limit', function(done) {
if(offset ===0) expect(body.prev).toBeNull();
else expect(body.prev).toEqual(baseUrl + '?limit=' + limit + '&offset=' + (offset - limit));
done();
});
it('should have "next" navigation link equal to offset + limit, or null if offset+limit > count', function(done) {
if(offset + limit <= count) expect(body.next).toEqual(baseUrl + '?limit=' + limit + '&offset=' + (offset + limit));
else expect(body.next).toBeNull();
done();
});
it('should have "last" navigation link equal to floor(count/limit)*limit', function(done) {
expect(body.last).toEqual(baseUrl + '?limit=' + limit + '&offset=' + Math.floor(count/limit) * limit);
done();
});
})(offset, count, limit);
}
Моя вторая идея состояла в том, чтобы сделать увеличивающиеся внутри «Afterall», снова заворачивая испытаний в IIFE. Кажется, что Afterall мчит runTests() еще раз (я вижу console.log появляющийся), но сами тесты не выполняются снова:
(function runTests(offset, count, limit) {
console.log('running tests');
beforeEach(function(done) {
request.get(url, function(err, res, resBody) {
response = res;
body = JSON.parse(resBody);
count = body.count;
done();
});
});
it('should have "first" navigation link equal to url offset=0 and limit=limit', function(done) {
expect(body.first).toEqual(baseUrl + '?limit=' + limit + '&offset=0');
done();
});
it('should have "prev" navigation link equal to null if offset=0, otherwise offset = offset - limit', function(done) {
if(offset ===0) expect(body.prev).toBeNull();
else expect(body.prev).toEqual(baseUrl + '?limit=' + limit + '&offset=' + (offset - limit));
done();
});
it('should have "next" navigation link equal to offset + limit, or null if offset+limit > count', function(done) {
console.log('next', offset, limit, count);
if(offset + limit <= count) expect(body.next).toEqual(baseUrl + '?limit=' + limit + '&offset=' + (offset + limit));
else expect(body.next).toBeNull();
done();
});
it('should have "last" navigation link equal to floor(count/limit)*limit', function(done) {
expect(body.last).toEqual(baseUrl + '?limit=' + limit + '&offset=' + Math.floor(count/limit) * limit);
done();
});
afterAll(function() {
offset += limit;
if(offset < count) runTests(offset, count, limit);
});
})(offset, count, limit);
Что я здесь делаю неправильно? Есть ли другой способ заставить это работать?
UPDATE: вот мой полный рабочий код, основанный на ответ Златко в:
describe('API with "limit" and "offset" parameters', function() {
var offset = 0;
var limit = 4;
var url = baseUrl + '?limit=' + limit + '&offset=' + offset;
function testNavLinks(limit, offset, url) {
describe('Check navigation links with offset = ' + offset, function() {
var response;
var count;
var body;
beforeEach(function(done) {
request.get(url, function(err, res, resBody) {
response = res;
body = JSON.parse(resBody);
count = body.count;
done();
});
});
it('should respond with status code 200', function(done) {
expect(response.statusCode).toEqual(200);
done();
});
it('should have a response with [limit] results if count - offset >= limit, otherwise count - offset', function(done) {
if(count - offset >= limit) expect(body.rows.length).toEqual(limit);
else expect(body.rows.length).toEqual(count - offset);
done();
});
it('should have navigation links', function(done) {
expect(body.first).toBeDefined();
expect(body.prev).toBeDefined();
expect(body.next).toBeDefined();
expect(body.last).toBeDefined();
done();
});
it('should have "first" navigation link equal to url offset=0 and limit=limit', function(done) {
expect(body.first).toEqual(baseUrl + '?limit=' + limit + '&offset=0');
done();
});
it('should have "prev" navigation link equal to null if offset=0, otherwise offset = offset - limit', function(done) {
if(offset === 0) expect(body.prev).toBeNull();
else expect(body.prev).toEqual(baseUrl + '?limit=' + limit + '&offset=' + (offset - limit));
done();
});
it('should have "next" navigation link equal to offset + limit, or null if offset+limit > count', function(done) {
if(offset + limit <= count) expect(body.next).toEqual(baseUrl + '?limit=' + limit + '&offset=' + (offset + limit));
else expect(body.next).toBeNull();
done();
});
it('should have "last" navigation link equal to floor(count/limit)*limit', function(done) {
expect(body.last).toEqual(baseUrl + '?limit=' + limit + '&offset=' + Math.floor(count/limit) * limit);
done();
});
});
}
// 13 is the actual number of results
// I did not manage to get the actual number from the response, see my comment below
for(var i=0; i<13; i+=limit) {
url = baseUrl + '?limit=' + limit + '&offset=' + i;
testNavLinks(limit, i, url);
}
});
Спасибо, я получил это сейчас. Единственным недостатком является то, что мне приходится жестко кодировать количество результатов (переменную count) в for-loop. Моя идея состояла в том, чтобы получить число результатов в родительском «описать», но это не работает, поскольку for-loop, по-видимому, запускается до запуска каких-либо спецификаций (я вижу console.log внутри цикла как самый первый вывод) –
Не уверен, что я понял, о чем вы просите, но если да, то вы также можете сделать 'beforeEach()' во внешнем 'описании' и запустить цикл for оттуда? Хм. Я просто задаюсь вопросом, будет ли он обработан, потому что «каждый» не запускается раньше каждого раньше :) – Zlatko