Angular Unit Testing mit Jasmine: Entfernen oder Ändern von SpyOn

71

AngularJS v1.2.26

Jasmine v2.2.0

Wie kann ich das Verhalten von a ändern oder entfernen spyOn? Wenn ich versuche, es zu überschreiben, wird folgende Fehlermeldung angezeigt:Error: getUpdate has already been spied upon

var data1 = 'foo';
var data2 = 'bar';

describe("a spec with a spy", function(){

    beforeEach(module('app'));

    var $q;

    beforeEach(inject(function(_updateService_, _$q_){
        updateService = _updateService_;

        //spy the results of the getUpdate()
        $q = _$q_;
        var deferred = $q.defer();
        deferred.resolve( data1 );
        spyOn(updateService, 'getUpdate').and.returnValue(deferred.promise);

    }));

    describe('and here the spy should be different', function() {

        it('returns a different value', function() {

          var deferred = $q.defer();
          deferred.resolve( data2 );
          spyOn(updateService, 'getUpdate'); //ERROR HERE
          updateService.getUpdate.and.returnValue(deferred.promise);

          ...

        });
    });

...

Wenn ich den zweiten SpyOn entferne, funktioniert der Test nicht.

Wie mache ich das?

emersonthis
quelle
Mögliches Duplikat von Jasmine Spy Bei derselben Methode mehr als einmal
Bohdan Lyzanets

Antworten:

89

Sie können es einfach überschreiben

updateService.getUpdate = jasmine.createSpy().and.returnValue(etc)
Peter Ashwell
quelle
4
Gibt es eine Möglichkeit, den Spion vollständig zu entfernen? Um zur ursprünglichen Funktion zurückzukehren?
Emersonthis
4
Die große Frage ist, wenn Sie nicht in jedem Test die gleiche Funktionalität haben, warum überhaupt einen globalen Spion? Wenn Sie den Spion für jeden Test festlegen möchten, legen Sie den Spion für jeden Test fest.
Januar
13
@Jan Wenn ich fünfzig Tests habe und nur einer von ihnen einen Spion für eine Funktion hat, die sich von den anderen unterscheidet, würde ich sie lieber nur einmal dort ändern, anstatt bei jedem einzelnen Test.
Theblang
1
In meinem Fall handelt es sich um ein globales Objekt (definiert durch nativen Code). Ich habe also mehrere Spezifikationen, die in verschiedenen Situationen unterschiedliche Werte zurückgeben müssen ...
FlavorScape
Würde es durch Aufrufen von jasmine.createSpy (). and.callThrought () zu seiner ursprünglichen Implementierung zurückkehren?
Aj gehen
29

Sie können den Rückgabewert des Spions überschreiben

    var deferred = $q.defer();
    deferred.resolve( data1 );

    var getUpdateSpy = spyOn(updateService, 'getUpdate').and.returnValue(deferred.promise);



    var newDeferred = $q.defer();
    newDeferred.resolve( data2 );

    getUpdateSpy.and.returnValue(newDeferred.promise);        
Javier Candalaft-CONT
quelle
1
Arbeiten am 18.6.2019
George C.
Das kann funktionieren, wenn Ihr gesamter Code in der gleichen Beschreibung ist, aber ansonsten nicht, weil getUpdateSpy nicht definiert ist ...
GarfieldKlon
@GarfieldKlon Sie können dies umgehen, indem Sie die Variable getUpdateSpyim übergeordneten describeBlock definieren.
Samuel Bushi
23

Verwenden Sie seit Jasmin v2.5 die globale allowRespy()Einstellung.

jasmine.getEnv().allowRespy(true);

Sie können spyOn()mehrmals anrufen , wenn Sie nicht möchten und / oder Zugriff auf den ersten Spion haben. Beachten Sie, dass der vorherige Spion zurückgegeben wird, falls einer bereits aktiv ist.

spyOn(updateService, 'getUpdate').and.returnValue(deferred.promise);
...
spyOn(updateService, 'getUpdate').and.returnValue(deferred.promise);

André Werlang
quelle
Ehrlich gesagt, das ist die Antwort, nach der ich seit Ewigkeiten gesucht habe. Ich wünschte, es wäre im Internet häufiger anzutreffen. Eine Million danke :)
Novastorm
8

Einfacher geht es zu einfach

updateService.getUpdate.and.returnValue(Observable.of({status:true}));
Aniruddha Das
quelle
Vielen Dank. Allen anderen fehlt die offensichtliche Antwort.
Camleng
4

Andere Option:

(yourService.method as jasmine.Spy).and.returnValue(value);
Justinas Jakavonis
quelle
2

Die Antwort mit dem grünen Häkchen hat bei mir nicht funktioniert, aber das hat funktioniert:

yourCoolService.createThing = jasmine.createSpy('notreal', function(){}).and.returnValue();

Ihr Jasmin-Test wird ausgeführt, aber wenn Sie das App-Typoskript starten, werden Sie laut angeschrien, wenn Sie keine zufällige Zeichenfolge und keine leere Funktion als Argumente verwenden createSpy().

rb1econ
quelle
1
Dies ist wahrscheinlich auf eine aktualisierte Version von Jasmine zurückzuführen. Ich benutze 2.7 und das funktioniert bei mir.
MBielski