63 votes

Jasmin - Espionnage sur un appel de méthode à l'intérieur d'un constructeur

Je veux tester si la méthode suivante est appelé dans mon Javascript constructeur de l'objet. De ce que j'ai vu dans le Jasmin de la documentation, je peux espionner un constructeur de méthode et je peux espionner les méthodes d'un objet a été instancié, mais je ne peux pas semblent être en mesure d'espionner une méthode avant que l'objet est construit.

L'objet:

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

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

Je veux faire quelque chose comme cela dans la spec:

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

111voto

Dave Newton Points 93112

Spy directement sur le prototype de la méthode:

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

12voto

alecmce Points 1129

Globalement, je suis d'accord avec Dave Newton réponse ci-dessus. Cependant, il y a quelques bords-cas à cette approche que vous devriez considérer.

Prendre une variation de Dave solution, avec un autre test:

// 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's 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(this.call_count).toEqual(1);
  });
});

Le deuxième test échoue car l'espion de l'installation dans le premier test persiste à travers le test des limites dans la seconde méthode; called_method n'a pas d'incrément call_count, donc c'.call_count n'est pas égale à 1. Il est également possible de venir avec des scénarios avec de faux positifs des tests qui passent, qui ne devrait pas.

Sur le dessus de cela, parce que l'espion reste, le plus Klass instances créées, plus le tas de la mémoire de l'espion va consommer, parce que le spy va enregistrer chaque appel à called_method. Ce n'est probablement pas un problème dans la plupart des cas, mais vous devriez être conscient de cela, juste au cas où.

Une solution simple à ce problème serait de faire en sorte que le spy est retiré après qu'il a été utilisé. Il peut paraître un peu moche, mais quelque chose comme cela fonctionne:

// test code
describe("The Klass constructor", function() {
  it("should call its prototype's 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;
  });

[NOTE - une petite opinion de terminer] Une meilleure solution serait de changer la façon dont vous écrivez le code de production pour rendre le code plus facile à tester. En règle générale, l'espionnage sur les prototypes est probablement un code-odeur à éviter. Au lieu d'instancier des dépendances dans le constructeur, de les injecter. Au lieu de faire l'initialisation dans le constructeur, de reporter à une méthode init.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X