Жасмин - как использовать методы экземпляра spyOn

У меня есть функция

var data = {};
var myFunc = function() {
  data.stuff = new ClassName().doA().doB().doC();
};

Я бы хотел проверить, что все doA, doB и doC были вызваны.

Я попытался шпионить за методами экземпляра вроде этого

beforeEach(function() {
  spyOn(ClassName, 'doA');
};
it('should call doA', function() {
  myFunc();
  expect(ClassName.doA)toHaveBeenCalled();
});

но это просто дает мне метод doA(), который не существует ".

Любые идеи?

Ответы

Ответ 1

Если вы поступили не так, было ваше понимание того, как ссылаться на методы в JavaScript в статическом контексте. То, что ваш код на самом деле делает, - это шпионить за ClassName.doA (то есть, функция, прикрепленная к конструктору ClassName как свойство doA), которая не является тем, что вы хотите).

Если вы хотите обнаружить, когда этот метод вызывается в любом экземпляре ClassName в любом месте, вам нужно заглянуть в прототип.

beforeEach(function() {
  spyOn(ClassName.prototype, 'doA');
});
it('should call doA', function() {
  myFunc();
  expect(ClassName.prototype.doA).toHaveBeenCalled();
});

Конечно, это предполагает, что doA живет в цепочке прототипов. Если это собственная собственность, то нет никакой техники, которую вы можете использовать, не имея возможности ссылаться на анонимный объект в myFunc. Если у вас был доступ к экземпляру ClassName внутри myFunc, это было бы идеально, поскольку вы могли бы просто spyOn создать этот объект напрямую.

P.S. Вы действительно должны поставить "Жасмин" в названии.

Ответ 2

Давайте сделаем некоторый рефакторинг кода, так как мы хотим реализовать шаблон внедрения конструктора , поскольку Джеймс Шор упоминает, что:

Впрыскивание зависимостей дает объект своим собственным переменным экземпляра. В самом деле. Вот оно.

var data = {};
var stuff = new ClassName()

var myFunc = function(stuff) { // move step of creation new object outside
  data.stuff = stuff.doA().doB().doC();
};

И время для некоторых тестов

function ClassName() {
}

var data = {};
var stuff = new ClassName()

var myFunc = function(stuff) {
  data.stuff = stuff.doA().doB().doC();
};


describe('stub for ClassName implementation', function() {
  var stubStuff = {
    doA: function() {
      return stubStuff
    },
    doB: function() {
      return stubStuff
    },
    doC: function() {
      return stubStuff
    }
  }

  beforeEach(function() {
    spyOn(stubStuff, 'doA').and.callThrough();
  });

  it('calls "doA" on "myFunc" exection', function() {
    myFunc(stubStuff);
    expect(stubStuff.doA).toHaveBeenCalled();
  });
});
<link href="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine.css" rel="stylesheet" />
<script src="//safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine-2.0.3-concated.js"></script>