Асинхронное тестирование с обратным вызовом с помощью Jasmine

Я пытаюсь протестировать модуль (использующий браузер для сборки), который выполняет XMLHttpRequest. Модуль выглядит так:

module.exports = function(year, cb) {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', encodeURI('data/' + year + '.json'));
  xhr.onload = function() {
    if (xhr.status === 200) {
      var counties = JSON.parse(xhr.responseText);
      cb(counties);
    } else {
      cb(xhr.status);
    }
  };
  xhr.send();
};

Мой тест Жасмин выглядит так:

var counties = require('myModule');

describe('did ajax call respond', function() {
  var countyList;

  beforeEach(function(done) {
    counties(2015, function(data) {
      countyList = data;
    });
    done();
  });

  it('should return', function(done) {
    console.log(countyList);
    expect(countyList).not.toEqual({});
    expect(countyList).not.toBeUndefined();
    done();
  });
});

Я видел этот вопрос - Почему Jasmine не выполняется it() в этом асинхронном тесте? - похоже, это то же самое, но все еще не работает.

Я получаю undefined за countyList. Мой выход жасмина:

did ajax call respond
    X should return
        Expected undefined not to be undefined. (1)

Спасибо за любую помощь!


person awolfe76    schedule 17.11.2015    source источник


Ответы (1)


Ваш done() находится не в том месте. Он должен быть внутри функции обратного вызова, переданной counties:

beforeEach(function(done) {
  counties(2015, function(data) {
    countyList = data;
    done();
  });
});

Это гарантирует, что методы it будут вызываться только после выполнения done, то есть после того, как data вернется, и у вас уже есть countyList.

person Buzinas    schedule 17.11.2015
comment
Так что это приблизило меня, спасибо. Но теперь ошибка: Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL. (1) Я думал, что этого не произойдет с этим решением. Любые идеи? - person awolfe76; 17.11.2015
comment
Вы пытались установить эту переменную в начале? вероятно, xhr занимает больше времени, чем Жасмин ждет. Вы могли бы, например, попытаться установить его на 10000 перед вызовами beforeEach/it. Но гораздо лучше: вы можете использовать async/await из ES7, а затем транспилировать их через Babel. - person Buzinas; 17.11.2015
comment
Извините, @Buzinas, не уверен, что вы имеете в виду ... вы пытались установить эту переменную в начале? вероятно, xhr занимает больше времени, чем Жасмин ждет. Вы могли бы, например, попытаться установить его на 10000 перед вызовом beforeEach/it. - person awolfe76; 17.11.2015
comment
@awolfe76 например: jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; beforeEach(function(done) { /* (...) */ }); it('should (...)', function(done) { /* (...) */ });, понял? - person Buzinas; 17.11.2015
comment
Вы можете передать второй параметр в beforeEach, который устанавливает время ожидания. например beforeEach(function(){ // делаем что-то }. 3000); - person Astravagrant; 27.04.2016