Как проверить метод в Jasmine, если код в `beforeEach` является асинхронным?
Я пытаюсь написать некоторые тесты с Jasmine, но теперь у меня проблема, если какой-то код асинхронен в beforeEach
.
Пример кода выглядит так:
describe("Jasmine", function() {
var data ;
beforeEach(function(){
console.log('Before each');
getSomeDataFromRemote(function(res){
data = res;
});
});
it("test1", function() {
expect(data).toBe(something);
console.log('Test finished');
});
});
Вы можете видеть, что в beforeEach
я хочу получить некоторые данные с удаленного устройства и назначить его data
асинхронно.
Но в test1
, когда я пытаюсь проверить:
expect(data).toBe(something);
Данные undefined
, потому что getSomeDataFromRemote
еще не закончен.
Как это исправить?
Ответы
Ответ 1
Так же, как и асинхронный материал в it
, вы можете использовать runs
и waitsFor
в вашем beforeEach:
define( 'Jasmine' , function () {
var data ;
beforeEach(function(){
runs( function () {
getSomeDataFromRemote(function(res){
data = res;
});
});
waitsFor(function () { return !!data; } , 'Timed out', 1000);
});
it("test1", function() {
runs( function () {
expect(data).toBe(something);
});
});
});
Хотя я собираюсь предположить, что это потому, что это был тестовый код, я думаю, что вы, вероятно, должны иметь вызов getSomeDataFromRemote
внутри вашего it
, как на самом деле то, что вы тестируете;)
В некоторых тестах, которые я написал для асинхронного API, вы можете увидеть несколько более крупных примеров: https://github.com/aaronpowell/db.js/blob/f8a1c331a20e14e286e3f21ff8cea8c2e3e57be6/tests/public/specs/open-db.js
Ответ 2
Жасмин 2.0
Будьте осторожны, потому что в новом Jasmine 2.0 это изменится, и это будет стиль мокко. Вы должны использовать функцию done()
в beforeEach()
и it()
. Например, представьте, что вы хотите проверить, существует ли страница и не пуста, на сервере LAMP, используя jQuery $.get
. Сначала вам нужно добавить jQuery в файл SpecRunner.html
и в файл spec.js
:
describe('The "index.php" should', function() {
var pageStatus;
var contents;
beforeEach(function (done) {
$.get('views/index.php', function (data, status) {
contents = data;
pageStatus = status;
done();
}).fail(function (object, status) {
pageStatus = status;
done();
});
});
it('exist', function(done) {
expect(status).toBe('success');
done();
});
it('have content', function(done) {
expect(contents).not.toBe('');
expect(contents).not.toBe(undefined);
done();
});
});
Как вы можете видеть, вы передаете функцию done()
в качестве параметра для beforeEach()
и it()
. Когда вы запустите тест, it()
не будет запущен до тех пор, пока done()
не будет вызван в функции beforeEach()
, поэтому вы не будете запускать ожидания до тех пор, пока не получите ответ от сервера.
Страница существует
Если страница существует, мы фиксируем статус и данные из ответа сервера, и вызываем done()
. Затем мы проверяем, является ли статус "успешным", и если данные не пусты или undefined.
Страница не существует
Если страница не существует, мы фиксируем статус из ответа сервера, и вызываем done()
. Затем мы проверяем, не является ли статус "успешным", а если данные пусты или undefined (это должно быть потому, что файл не существует).
Ответ 3
В этом случае я обычно закрываю асинхронный вызов для немедленного ответа.
Я не уверен, видели ли вы это или нет, но здесь - это какая-то документация об асинхронном тестировании с Jasmine.
Ответ 4
У меня есть подробная статья, описывающая, как тестировать асинхронные функции javascript, используя Jasmine: http://www.larsavery.com/blog/how-to-test-asynchronous-javascript-functions-using-jasmine/