angularjs - titel - title tag




Wie können Versprechen in AngularJS, Jasmine 2.0 gelöst werden, wenn es keinen Handlungsspielraum gibt, um einen Digest zu erzwingen? (3)

Es scheint, dass Versprechungen in Angular / Jasmine-Tests nicht gelöst werden, wenn Sie nicht einen $scope.$digest() erzwingen $scope.$digest() . Das ist dummes IMO aber okay, ich habe das, wo zutreffend, (Controller).

Die Situation, in der ich mich jetzt befinde, ist, dass ich einen Dienst habe, der sich weniger um den Geltungsbereich der Anwendung kümmern könnte, als er alle Daten vom Server zurückgibt, aber das Versprechen scheint sich nicht zu lösen.

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 ich diese Funktionalität testen?

Edit: Lösung als Referenz. Anscheinend sind Sie gezwungen, $ rootScope zu injizieren und zu verdauen, auch wenn der Dienst es nicht verwendet.

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

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

    $rootScope.$digest();
    done();
  }); 

Also habe ich den ganzen Nachmittag damit zu kämpfen. Nachdem ich diesen Beitrag gelesen hatte, hatte ich auch das Gefühl, dass etwas mit der Antwort nicht stimmt, es stellt sich heraus, dass es da ist. Keine der obigen Antworten gibt eine klare Erklärung, wo und warum $rootScope.$digest . Also hier ist was ich mir ausgedacht habe.

Zunächst einmal warum? Sie müssen $rootScope.$digest wenn Sie von einem nicht eckigen Ereignis oder einem Rückruf aus antworten. Dies würde reine DOM-Ereignisse, jQuery-Ereignisse und andere Promise-Bibliotheken von Drittanbietern mit Ausnahme von $q einschließen, das Teil von angle ist.

Zweitens wo? In Ihrem Code NICHT Ihren Test. Es ist nicht erforderlich, $rootScope in Ihren Test $rootScope , es wird nur in Ihrem tatsächlichen Winkel-Service benötigt. In diesem $rootScope.$digest nicht klargestellt werden, was die Antwort ist. Sie zeigen, dass $rootScope.$digest aus dem Test aufgerufen wird.

Ich hoffe, das hilft der nächsten Person, die ein langes kommt und das gleiche Problem hat.

Aktualisieren

Ich habe diesen Beitrag gestern gelöscht, als er abgelehnt wurde. Heute hatte ich weiterhin dieses Problem und versuchte, die Antworten zu verwenden, die mir freundlicherweise oben zur Verfügung gestellt wurden. Ich stehe also für meine Antwort auf Kosten von Reputationspunkten bereit und lösche sie daher als solche.

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

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

Beachten Sie, dass in einigen Fällen möglicherweise ein $ -Zeitlimit eingehalten werden muss.

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

Noch eine Notiz. In den ursprünglichen Problembeispielen rufen Sie zum falschen Zeitpunkt an. Sie müssen done innerhalb der then Methode (oder der catch oder finally ) des Versprechens aufrufen, nachdem sie aufgelöst ist. Sie rufen es an, bevor das Versprechen verrechnet wird, wodurch die Klausel it gekündigt wird.


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);
}));

Sie müssen $rootScope in Ihren Test injizieren und $digest darauf auslösen.







karma-jasmine