Подтвердить что ты не робот

Жасмин - шпионить за вызовом метода внутри конструктора

Я хочу проверить, вызван ли следующий метод в моем конструкторе объектов Javascript. Из того, что я видел в документации Jasmine, я могу отслеживать метод конструктора, и я могу следить за методами после того, как объект был создан, но я не вижу возможности отслеживать метод до того, как объект будет создан.

Объект:

Klass = function() {
    this.called_method();
};

Klass.prototype.called_method = function() {
  //method to be called in the constructor.
}

Я хочу сделать что-то подобное в спецификации:

it('should spy on a method call within the constructor', function() {
    spyOn(window, 'Klass');
    var obj = new Klass();
    expect(window.Klass.called_method).toHaveBeenCalled();
});
4b9b3361

Ответ 1

Шпион непосредственно по прототипу:

describe("The Klass constructor", function() {
  it("should call its prototype called_method", function() {
      spyOn(Klass.prototype, 'called_method');  //.andCallThrough();
      var k = new Klass();
      expect(Klass.prototype.called_method).toHaveBeenCalled();
  });
});

Ответ 2

В целом, я согласен с ответом Дейва Ньютона выше. Тем не менее, есть некоторые краевые случаи для этого подхода, которые вы должны учитывать.

Возьмите вариацию к решению Дэйва, с другим тестовым случаем:

// production code
var Klass = function() {
  this.call_count = 0;
  this.called_method();
};
Klass.prototype.called_method = function() {
  ++this.call_count;
};

// test code
describe("The Klass constructor", function() {
  it("should call its prototype called_method", function() {
    spyOn(Klass.prototype, 'called_method');
    var k = new Klass();
    expect(k.called_method).toHaveBeenCalled();
  });
  it('some other test', function() {
    var k = new Klass();
    expect(k.call_count).toEqual(1);
  });
});

Второе испытание завершится неудачно, потому что установка шпиона в первом тесте сохраняется во всех тестовых границах во втором методе; call_method не увеличивает значение call_count, поэтому this.call_count не равно 1. Также возможно вывести сценарии с ложными срабатываниями - те тесты, которые не проходят.

Вдобавок к этому, поскольку шпион остается, чем больше создаваемых экземпляров Klass, тем больше будет куча памяти, которую шпион будет потреблять, потому что шпион будет записывать каждый вызов вызываемому_методу. Вероятно, это не проблема в большинстве случаев, но на всякий случай вы должны знать об этом.

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

// test code
describe("The Klass constructor", function() {
  it("should call its prototype called_method", function() {
    var spy = jasmine.createSpy('called_method');
    var method = Klass.prototype.called_method;
    Klass.prototype.called_method = spy;
    var k = new Klass();
    expect(spy).toHaveBeenCalled();
    Klass.prototype.called_method = method;
  });

[ПРИМЕЧАНИЕ - небольшое мнение, чтобы закончить] Лучшим решением было бы изменить способ написания производственного кода, чтобы сделать код более легким для тестирования. Как правило, слежение за прототипами, вероятно, является кодовым запахом, которого следует избегать. Вместо инстанцирования зависимостей в конструкторе впрыскивайте их. Вместо выполнения инициализации в конструкторе отложите соответствующий метод init.