Wie löst man Versprechen in AngularJS, Jasmine 2.0 auf, wenn es keinen $scope gibt, um einen Digest zu erzwingen?

StackOverflow https://stackoverflow.com//questions/24021031

Frage

Das scheint vielversprechend Wird in Angular/Jasmine-Tests nicht aufgelöst, es sei denn, Sie erzwingen a $scope.$digest().Das ist meiner Meinung nach albern, aber in Ordnung, ich habe das, wo es anwendbar ist (Controller).

Die Situation, in der ich mich jetzt befinde, ist, dass ich einen Dienst habe, der sich weniger um Bereiche in der Anwendung kümmert. Er gibt lediglich einige Daten vom Server zurück, aber das Versprechen scheint nicht aufgelöst zu werden.

app.service('myService', function($q) {
  return {
    getSomething: function() {
      var deferred = $q.defer();
      deferred.resolve('test');
      return deferred.promise;
    }
  }
});

describe('Method: getSomething', function() {
  // In this case the expect()s are never executed
  it('should get something', function(done) {
    var promise = myService.getSomething();

    promise.then(function(resp) {
      expect(resp).toBe('test');      
      expect(1).toEqual(2);
    });

    done();
  });

  // This throws an error because done() is never called.
  // Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
  it('should get something', function(done) {
    var promise = myService.getSomething();

    promise.then(function(resp) {
      expect(resp).toBe('test');      
      expect(1).toEqual(2);
      done();
    });
  });
});

Wie kann diese Funktionalität richtig getestet werden?

Bearbeiten:Lösung als Referenz.Anscheinend sind Sie gezwungen, den $rootScope einzuschleusen und zu verarbeiten, auch wenn der Dienst ihn nicht verwendet.

  it('should get something', function($rootScope, done) {
    var promise = myService.getSomething();

    promise.then(function(resp) {
      expect(resp).toBe('test');      
    });

    $rootScope.$digest();
    done();
  }); 
War es hilfreich?

Lösung

Sie müssen spritzen $rootScope in Ihrem Test und Trigger $digest drauf.

Andere Tipps

Es gibt immer den $rootScope, verwenden Sie ihn

inject(function($rootScope){
myRootScope=$rootScope;
})
....

myRootScope.$digest();

Ich habe also den ganzen Nachmittag damit zu kämpfen.Nachdem ich diesen Beitrag gelesen hatte, hatte auch ich das Gefühl, dass mit der Antwort etwas nicht stimmte; es stellte sich heraus, dass es so war.Keine der oben genannten Antworten gibt eine klare Erklärung, wo und warum die Verwendung erfolgen soll $rootScope.$digest.Also, hier ist, was ich mir ausgedacht habe.

Zunächst einmal: Warum?Sie müssen verwenden $rootScope.$digest wann immer Sie auf ein nicht-angulares Ereignis oder einen Rückruf antworten.Dazu gehören reine DOM-Ereignisse, jQuery-Ereignisse und andere Promise-Bibliotheken von Drittanbietern als $q was Teil von eckig ist.

Zweitens: Wo?In Ihrem Code, NICHT in Ihrem Test.Eine Injektion ist nicht erforderlich $rootScope In Ihren Test wird es nur in Ihrem eigentlichen Winkeldienst benötigt.Das ist der Punkt, an dem all das oben Gesagte nicht klar macht, was die Antwort ist, zeigen sie $rootScope.$digest als vom Test abgerufen.

Ich hoffe, das hilft der nächsten Person, die das gleiche Problem hat.

Aktualisieren


Ich habe diesen Beitrag gestern gelöscht, als er abgelehnt wurde.Heute hatte ich weiterhin dieses Problem, als ich versuchte, die oben freundlicherweise bereitgestellten Antworten zu verwenden.Daher halte ich meine Antwort auf Kosten von Reputationspunkten bereit und stelle sie daher wieder her.

Dies ist, was Sie in nicht-eckigen Event-Handlern benötigen, und Sie verwenden $q und versuchen, mit Jasmine zu testen.

something.on('ready', function(err) {
    $rootScope.$apply(function(){deferred.resolve()});              
});

Beachten Sie, dass es in manchen Fällen möglicherweise in ein $timeout eingeschlossen werden muss.

something.on('ready', function(err) {
    $timeout(function(){
      $rootScope.$apply(function(){deferred.resolve()});    
    });     
});

Noch eine Anmerkung.In den ursprünglichen Problembeispielen rufen Sie an done zur falschen Zeit.Sie müssen anrufen done innerhalb der then Methode (oder die catch oder finally), des Versprechens, nachdem es aufgelöst wird.Sie rufen es auf, bevor das Versprechen aufgelöst wird, was die Ursache ist it Klausel zur Kündigung.

Aus der Winkeldokumentation.

https://docs.angularjs.org/api/ng/service/$q

it('should simulate promise', inject(function($q, $rootScope) {
  var deferred = $q.defer();
  var promise = deferred.promise;
  var resolvedValue;

  promise.then(function(value) { resolvedValue = value; });
  expect(resolvedValue).toBeUndefined();

  // Simulate resolving of promise
  deferred.resolve(123);
  // Note that the 'then' function does not get called synchronously.
  // This is because we want the promise API to always be async, whether or not
  // it got called synchronously or asynchronously.
  expect(resolvedValue).toBeUndefined();

  // Propagate promise resolution to 'then' functions using $apply().
  $rootScope.$apply();
  expect(resolvedValue).toEqual(123);
}));
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top