SpyOn метод просмотра позвоночника с использованием жасмина - PullRequest
18 голосов
/ 26 октября 2011

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

PromptView = Backbone.View.extend({
        id:"promptPage",
        attributes:{
            "data-role":"page",
            "data-theme":"a"
        },
        events:{
            "click #btnYes":    "answerYes",
            "tap #btnYes":      "answerYes"
        },
        render: function(){
            $(this.el).html(_.template($('#promptPage-template').html(), this.model.toJSON()));

            return this;
        },
        answerYes: function(){
            alert('yes');
        }
    });

Моя спецификация:

beforeEach(function() {
            model = new PromptModel;
            view = new PromptView({model:model});
            loadFixtures('promptPage.tmpl');
        });

 it("should be able to answer a question with yes", function() {
                var button = $("#btnYes", view.render().el);
                expect(button.length).toBe(1);

                spyOn(view, 'answerYes');

                button.click();
                expect(view.answerYes).toHaveBeenCalled();

            });

Однако приведенное выше определение представления создает метод answerYes для прототипа proto , но шпион создает функцию для фактического экземпляра в представлении, поэтому я получаю представление view.answerYes (), которое шпион и вид .__ proto __. answerYes, именно это я и хочу шпионить.

Как создать шпиона, чтобы он переопределял метод answerYes определения представления?

Ответы [ 5 ]

54 голосов
/ 28 октября 2011

Привет у меня сегодня была такая же проблема. И я только что нашел решение, после создания шпионского метода (answerYes) вы должны обновить события представления, чтобы вызвать этот новый шпионский метод;):

[...]

    spyOn(view, 'answerYes');
    <b>view.delegateEvents();</b>

    button.click();
    expect(view.answerYes).toHaveBeenCalled();

[...]

Дополнительная информация о делегатских мероприятиях

Веселись!

3 голосов
/ 05 июля 2013

Это создает шпиона для answerYes метода PromptView:

spyOn(PromtView.prototype, 'answerYes');
3 голосов
/ 21 ноября 2012

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

1 голос
/ 26 октября 2011

TL; DR: следите за методом экземпляра, а не за прототипом.

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

beforeEach(function() {
  loadFixtures('promptPage.tmpl');

  var model = new PromptModel();
  this.view = new PromptView({model:model});
  this.view.render();

  this.button = this.view.$("#btnYes");
});

it("should render the button", function(){
  expect(this.button.length).toBe(1);
});

it("should be able to answer a question with yes", function() {
  spyOn(this.view, 'answerYes');

  this.button.click();
  expect(this.view.answerYes).toHaveBeenCalled();
});

Вам не нужно строго рассчитывать длину кнопки. Если кнопка не имеет длины (не найдена), вы получите другие сбои. Но, возможно, вы захотите сделать это, чтобы было проще понять, что представление не отображается правильно.

Вы должны также шпионить за экземпляром view, как вы это делали. Определение PromptView добавляет метод answerYes к прототипу, да, но тот, за кем вы хотите следить, - это экземпляр представления, а не прототип.

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

0 голосов
/ 25 июня 2015

Если у вас возникли проблемы с использованием spyOn, вы можете подумать о создании шпиона. Так что-то вроде:

var eventSpy;
eventSpy = jasmine.createSpy('eventSpy');
view.$el.on('myCustom:event', eventSpy);
...