Тестирование модели связывания в Backbone JS с жасмином - PullRequest
3 голосов
/ 14 января 2012

У меня есть представление, которое содержит модель.Представление прослушивает событие из модели и выполнит действие после его запуска.Ниже мой код

window.Category = Backbone.Model.extend({})

window.notesDialog = Backbone.View.extend({
  initialize: function() {
    this.model.bind("notesFetched", this.showNotes, this);
  },
  showNotes: function(notes) {
    //do stuffs here
  }
})

Я хочу проверить это с помощью Jasmine, а ниже мой тест (который не работает)

it("should show notes", function() {
   var category = new Category;

   var notes_dialog = new NotesDialog({model: category})

   spyOn(notes_dialog, "showNotes");
   category.trigger("notesFetched", "[]");
   expect(notes_dialog.showNotes).toHaveBeenCalledWith("[]");
})

Кто-нибудь знает, почему вышеупомянутый тест не 'т работаешь?Я получаю сообщение об ошибке: «Ожидаемые шпионские showNotes были вызваны с ['[]'], но никогда не вызывались».

Ответы [ 5 ]

7 голосов
/ 01 февраля 2012

Я делал что-то похожее, когда у меня было представление, но я не мог заставить шпиона работать должным образом, пока я не добавил его в прототип и не создал экземпляр вида.

Вотчто в итоге сработало для меня:

view.js

view = Backbone.View.extend({
   initialize: function(){
      this.collection.bind("change", this.onChange, this);
   },
   ...
   onChange: function(){
      console.log("Called...");
   }
});

jasmine_spec.js

describe("Test Event", function(){
   it("Should spy on change event", function(){
      var spy = spyOn(view.prototype, 'onChange').andCallThrough()
      var v = new view( {collection: some_collection });

      // Trigger the change event
      some_collection.set();

      expect(spy).toHaveBeenCalled()
   });
});

Сначала я бы протестировал с ожиданием toHaveBeenCalled() и изменил бы наtoHaveBeenCalledWith() после того, как вы это заработаете ...

Обновление от 06.05.2013: изменено update() на set()

3 голосов
/ 13 июня 2012

Попробуйте изменить существующий код теста следующим образом:

it("should show notes", function() {
   var category = new Category;

   spyOn(NotesDialog.prototype, "showNotes");
   var notes_dialog = new NotesDialog({model: category})

   category.trigger("notesFetched", "[]");
   expect(notes_dialog.showNotes).toHaveBeenCalledWith("[]");
})

В вашем исходном коде экземпляр метода, который вы вызываете, определен в закрытии привязки, тогда как тот, на который вы следите, находится в экземпляре notes_dialog. Перемещая шпиона в прототип, вы заменяете его до того, как происходит связывание, и поэтому закрытие связывания инкапсулирует шпиона, а не оригинальный метод.

1 голос
/ 15 января 2012

Использование шпиона означает замену функции, на которую вы шпионите.Таким образом, в вашем случае вы заменяете функцию связывания шпионом, поэтому внутренняя логика исходного шпиона больше не будет вызываться.И это правильный путь, потому что вы не хотите проверять, что Backbones bind работает, но вы позвонили bind с определенными параметрами "notesFetched", this.showNotes, this.

Так как это проверить.Как вы знаете, у каждого шпиона есть метод toHaveBeenCalledWith(arguments).В вашем случае это должно выглядеть так:

expect(category.bind).toHaveBeenCalledWith("notesFetched", category. showNotes, showNotes)

Итак, как протестировать этот триггер «notesFetched» на модели вызовет вашу функцию showNotes.Каждый шпион сохраняет все параметры, с которыми ему звонили.Вы можете получить доступ к последнему с помощью mostRecentCall.args.

category.bind.mostRecentCall.args[1].call(category.bind.mostRecentCall.args[2], "[]");
expect(notes_dialog.showNotes).toHaveBeenCalledWith("[]");

mostRecentCall.args[1] - второй аргумент в вашем вызове bind (this.showNotes).mostRecentCall.args[2] является третьим аргументом в вашем вызове связывания (this).

Поскольку у нас есть проверка, что bind был вызван вашим открытым методом showNotes, вы также можете вызвать ваш открытый методshowNotes напрямую, но иногда переданные аргументы могут получить доступ извне, поэтому вы будете использовать показанный путь.

0 голосов
/ 07 февраля 2012

Вы довольно близки;) spyOn заменяет функцию вашим шпионом и возвращает вам шпиона.Так что если вы делаете:

   var dialog_spy = spyOn(notes_dialog, "showNotes");
   category.trigger("notesFetched", "[]");
   expect(dialog_spy).toHaveBeenCalledWith("[]");

должно работать просто отлично!

0 голосов
/ 14 января 2012

Ваш код выглядит нормально, за исключением того, что у вас есть тест, заключенный в функцию description, а также в функцию it?


describe("show notes", function(){
  it("should show notes", function(){
    // ... everything you already have here
  });
});

Общее предположение на данный момент, но поскольку вы не показываетеопишите функцию, это все, что я могу себе представитьУ вас должен быть блок описания, чтобы тесты работали, если у вас его нет.

...