86 votes

Comment effacer les espions de manière programmatique dans Jasmine ?

Comment effacer l'espion dans une suite de test jasmine de manière programmatique ? Merci.

beforeEach(function() {
  spyOn($, "ajax").andCallFake(function(params){
  })
})

it("should do something", function() {
  //I want to override the spy on ajax here and do it a little differently
})

4 votes

Vous êtes sûr d'avoir choisi la bonne réponse "correcte" ?

141voto

Alissa Points 116

Réglage isSpy à false est une très mauvaise idée, car alors vous espionnez un espion et lorsque Jasmine efface les espions à la fin de votre spécification, vous n'obtiendrez pas la méthode originale. la méthode sera égale au premier espion.

si vous espionnez déjà une méthode et que vous voulez que la méthode originale soit appelée à la place, vous devez appeler andCallThrough() qui remplacera le premier comportement de l'espion.

par exemple

var spyObj = spyOn(obj,'methodName').andReturn(true);
spyObj.andCallThrough();

vous pouvez effacer tous les espions en appelant this.removeAllSpies() ( this - spec)

47voto

uglymunky Points 1594

Je pense que c'est ce que .reset() est pour :

spyOn($, 'ajax');

$.post('http://someUrl', someData);

expect($.ajax).toHaveBeenCalled();

$.ajax.calls.reset()

expect($.ajax).not.toHaveBeenCalled();

14 votes

Tout ce que cela fait, c'est réinitialiser l'état de suivi. Si vous cherchez à rétablir le comportement par défaut, cela ne vous aidera pas.

20 votes

Notez que cela a changé en mySpy.calls.reset() dans Jasmine 2.

1 votes

mySpy.calls.reset() réinitialise le compteur de fois où l'espion a été appelé. Vous pouvez le vérifier avec expect(spy).toHaveBeenCalledTimes(1)

21voto

FilmJ Points 988

Donc les espions sont réinitialisés automatiquement entre les spécifications.

En fait, vous ne bénéficiez pas de la "restauration" de la fonction originale si vous utilisez andCallFake() dans un beforeEach() et ensuite tenter de le modifier de force dans une spécification (c'est probablement pour cela qu'il essaie de vous en empêcher).

Soyez donc prudent, surtout si votre espion est placé sur un objet global tel que jQuery.

Démonstration :

var a = {b:function() { return 'default'; } }; // global scope (i.e. jQuery)
var originalValue = a.b;

describe("SpyOn test", function(){
  it('should return spy1', function(){
    spyOn(a, 'b').andCallFake(function(params) {
      return 'spy1';
    })
    expect(a.b()).toEqual('spy1');
  });

  it('should return default because removeAllSpies() happens in teardown', function(){
    expect(a.b()).toEqual('default');
  });

  it('will change internal state by "forcing" a spy to be set twice, overwriting the originalValue', function(){
    expect(a.b()).toEqual('default');

    spyOn(a, 'b').andCallFake(function(params) {
      return 'spy2';
    })
    expect(a.b()).toEqual('spy2');

    // This forces the overwrite of the internal state
    a.b.isSpy = false;
    spyOn(a, 'b').andCallFake(function(params) {
      return 'spy3';
    })
    expect(a.b()).toEqual('spy3');

  });

  it('should return default but will not', function(){
    expect(a.b()).toEqual('default'); // FAIL

    // What's happening internally?
    expect(this.spies_.length).toBe(1);
    expect(this.spies_[0].originalValue).toBe(originalValue); // FAIL
  });

});

describe("SpyOn with beforeEach test", function(){
  beforeEach(function(){
    spyOn(a, 'b').andCallFake(function(params) {
      return 'spy1';
    })
  })

  it('should return spy1', function(){
    // inspect the internal tracking of spies:
    expect(this.spies_.length).toBe(1);
    expect(this.spies_[0].originalValue).toBe(originalValue);

    expect(a.b()).toEqual('spy1');
  });

  it('should return spy2 when forced', function(){
    // inspect the internal tracking of spies:
    expect(this.spies_.length).toBe(1);
    expect(this.spies_[0].originalValue).toBe(originalValue);

    // THIS EFFECTIVELY changes the "originalState" from what it was before the beforeEach to what it is now.
    a.b.isSpy = false;
    spyOn(a, 'b').andCallFake(function(params) {
        return 'spy2';
    })
    expect(a.b()).toEqual('spy2');
  });

  it('should again return spy1 - but we have overwritten the original state, and can never return to it', function(){
    // inspect the internal tracking of spies:
    expect(this.spies_.length).toBe(1);
    expect(this.spies_[0].originalValue).toBe(originalValue); // FAILS!

    expect(a.b()).toEqual('spy1');
  });
});

// If you were hoping jasmine would cleanup your mess even after the spec is completed...
console.log(a.b == originalValue) // FALSE as you've already altered the global object!

0 votes

J'essayais de savoir ce que je devais faire pour arrêter d'espionner un objet. Votre réponse est très claire et utile. Et jasmine est génial pour s'en occuper automatiquement lors du démontage.

10voto

titusd Points 486

Dans Jasmine 2, l'état de l'espion est conservé dans une instance de SpyStrategy. Vous pouvez obtenir cette instance en appelant $.ajax.and . Voir le code source de Jasmine sur GitHub .

Donc, pour définir une fausse méthode différente, faites ceci :

$.ajax.and.callFake(function() { ... });

Pour revenir à la méthode originale, procédez comme suit :

$.ajax.and.callThrough();

2 votes

Je ne pense pas que $.ajax.and.andCallThrough(); est correcte. Devrait être $.ajax.and.callThrough();

0 votes

Cela a marché pour moi ; à l'intérieur beforeEach : spyOn(Foobar, 'getFoo').and.returnValue('generic'); } puis à l'intérieur it : Foobar.getFoo.and.returnValue('special') . Merci !

0 votes

C'est la bonne réponse. Je fais la même chose. J'ai eu l'idée de ce post : github.com/jasmine/jasmine/issues/160 . Je ne comprends pas pourquoi ce n'est pas la meilleure réponse ?

7voto

user7054363 Points 71

Cela a fonctionné pour moi dans Jasmine 2.5 pour permettre le réajustement de l'ajax fantaisie.

function spyOnAjax(mockResult) {
    // must set to true to allow multiple calls to spyOn:
    jasmine.getEnv().allowRespy(true);

    spyOn($, 'ajax').and.callFake(function () {
        var deferred = $.Deferred();
        deferred.resolve(mockResult);
        return deferred.promise();
    });
}

Vous pouvez alors l'appeler plusieurs fois sans erreur. spyOnAjax(mock1) ; spyOnAjax(mock2) ;

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