jeudi 26 novembre 2015

How to test a method returning a promise with Karma/Jasmine in Angular

I'm new to angular, promises and karma. Since this morning I'm stuck trying to test a method that returns a promise using Karma/Jasmine in Angular.

I have this angular service where I use Promises as I saw here

angular.module('app')
    .service('myService', myService);

function myService() {
    this.get = function(id) {
        return new Promise(function(resolve, reject) {
            if(id === 1) {
                //DOSOMETHING
                resolve('banana');
            } else {
                //DOSOMETHINGELSE
                resolve('papaya');
            }
        });
    };
}

so that I can use it this way in my code:

myService.get(value).then(...);

Searching on stackoverflow I've found a lot of working examples but no one works for me.

For example this one:

describe('how to test with promises', function () {
  var deferred, $rootScope;

  beforeEach(function () {
    inject(function ($q, _$rootScope_) {
      $rootScope = _$rootScope_;
      deferred = $q.defer();
    });
  });

  it('does a thing one way', function () {
    var handler = jasmine.createSpy('success');
    deferred.promise.then(handler);
    deferred.resolve(4);
    $rootScope.$digest();
    expect(handler).toHaveBeenCalledWith(4);
  });

  it('does a thing another way', function() {
    var value;
    deferred.promise.then(function(_value_) {
        value = _value_;
    });
    deferred.resolve(10);
    expect(value).not.toBe(10); // not yet 10 because $digest hasn't run
    $rootScope.$digest();
    expect(value).toBe(10); // 10 because $digest already ran
});

The best I achieved is this, that I know is really really bad (and still doesn't works):

  beforeEach(module('app'));
  var myService, $rootScope, deferred;
  beforeEach(inject(function($q,_$rootScope_, _myService_) {
    $rootScope = _$rootScope_;
    myService = _myService_;
    deferred = myService.get(1);
    var temp = $q.defer();
    temp.promise = deferred; 
    deferred = temp; 
  }));

  describe('how much I am noob with testing', function() {
    it('does a thing another way', function() {
      var value;
      deferred.promise.then(function(_value_) {
        value = _value_;
      });
      // deferred.resolve(10);
      expect(value).not.toBe('banana');
      $rootScope.$digest();
      expect(value).toBe('banana');
    });
  });

This is the only way I've found to execute my promise, but after the $digest, value is still undefined.

I'm clearly confused, I'm probably misunderstanding how to use Promises. If someone can help I would really appreciate!

Aucun commentaire:

Enregistrer un commentaire