3

Jasmine 2.0 でバックボーン ビューをテストしています。ビューは、ロード時に最初の ajax リクエストを作成して、フォーム フィールドに値を入力します。itこれらの値が受信された後にのみ、Jasmine テスト (以下の関数内) を実行したいと考えています。

ajax リクエストをスタブしているにもかかわらず、テストの実行後に ajax リクエストが受信されたように見えるため、現在、テストは失敗しています。

このテストはどのように記述すればよいですか?

describe('View', function() {

  var formFieldValues = [/* blah */];
  var view;

  beforeEach(function(done) {
    jasmine.Ajax.install();
    jasmine.Ajax.stubRequest('/form-fields').andReturn({
      responseJSON: formFieldValues
    });
    view = new View({el: $('<main></main>')}); // makes ajax call on initialization
    $('body').append(view.el);
  });

  afterEach(function() {
    view.remove();
    jasmine.Ajax.uninstall();
  });

  it('form fields have values', function(done) {
    // PROBLEM IS HERE: THE FOLLOWING RUNS BEFORE VIEW'S AJAX CALL FINISHES
    expect(view.$('[name="fieldName"]').children().length).toEqual(formFieldValues.length);
  });

});
4

2 に答える 2

6

実際に非同期仕様を実行しているようには見えません。あなたbeforeEachit両方がコールバックを受信して​​いることに気付きdoneましたが、どちらもそれを呼び出していません。また、ajax をスタブ化する場合は、おそらく async 仕様を実行する必要はありません。スタブによって実質的に ajax リクエストが同期化されるからです。

次のコードを実行すると、すべて正常に動作します。

仕様:

describe('View', function() {

  var formFieldValues = [{name: 'foo'}, {name: 'bar'}];
  var view;

  beforeEach(function() {
    jasmine.Ajax.install();
    jasmine.Ajax.stubRequest('/form-fields').andReturn({
      responseText: JSON.stringify(formFieldValues)
    });
    view = new View(); // makes ajax call on initialization
  });

  afterEach(function() {
    jasmine.Ajax.uninstall();
  });

  it('form fields have values', function() {
    // PROBLEM IS HERE: THE FOLLOWING RUNS BEFORE VIEW'S AJAX CALL FINISHES
    expect(view.$('[name="fieldName"]').children().length).toEqual(formFieldValues.length);
  });

});

私のダミーの実装:

Collection = Backbone.Collection.extend({
  url: '/form-fields'
});

View = Backbone.View.extend({
  initialize: function() {
    this.collection = new Collection();
    this.collection.on('reset', this.render, this);
    this.collection.fetch({reset: true});
  },

  render: function() {
    var innerEl = $('<div name="fieldName"></div>')
    this.collection.each(function(item) {
      innerEl.append('<span></span>');
    });
    this.$el.append(innerEl);
  }
});
于 2014-03-08T04:00:54.623 に答える
0

非同期にするには、runs() および waitFor() メソッドを使用する必要があります。run() メソッドの呼び出しは個別のテスト ブロックとして機能し、その最後のブロックで非同期呼び出しが行われます。最も単純なケースでは、 setTimeout() を使用して非同期動作をシミュレートできます。より複雑な使用法では、Ajax 対応オブジェクトなどに対して実際の呼び出しが行われます。

waitsFor() メソッドは、「ラッチ」関数、失敗メッセージ、タイムアウト (ミリ秒単位) の 3 つの引数を受け入れます。

runs(function() {
    flag = false;
    value = 0;

setTimeout(function() {
  value++;
  //keep returning false…
  flag = false;
}, 500);
  });

  waitsFor(function() {
    return flag;
  }, "The Value should be incremented", 5000);
});

または、Making Real Ajax Requests を試すことができます

統合テストを実行するときが来たら、Ajax 呼び出しを単に模倣するのではなく、実際の Ajax 呼び出しを実行したいと思うでしょう。問題ない。スパイを作成し、Ajax 呼び出しを行い、続いて waitsFor() を実行します。ここで、callback.callCount プロパティまたは what-have-you を確認できます。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

it("should make a real AJAX request", function () {
    var callback = jasmine.createSpy();
    makeAjaxCall(callback);
    waitsFor(function() {
        return callback.callCount > 0;
    }, "The Ajax call timed out.", 5000);

    runs(function() {
        expect(callback).toHaveBeenCalled();
    });
});

function makeAjaxCall(callback) {
    $.ajax({
        type: "GET",
        url: "data.json",
        contentType: "application/json; charset=utf-8"
        dataType: "json",
        success: callback
    });
}
于 2014-03-12T05:59:20.490 に答える