monnef
monnef

Reputation: 4053

Frozen promise in a unit test

I have hit a strange thing when trying to test a service returning ordinary $q promise. No promise I try in any test is actually being ever resolved/rejected (more specifically handlers from then are not called, code inside promise runs just fine). I even tried forcing digest on a root scope, as some other answers on SO suggested, without any luck.

Here is a small self-contained example:

describe('promise', function(){
  jasmine.DEFAULT_TIMEOUT_INTERVAL = 500;
  let q;

  beforeEach(inject(function($q){
    q = $q;
  }));

  it('finishes', function(done){
    expect(q).toBeDefined();
    const promise = q.resolve();
    console.log(promise);
    promise.then(
      () => done(),
      () => done.fail()
    );
  });
});

What do I have to do to get the promise work as expected?

Upvotes: 0

Views: 71

Answers (2)

Radek Wyroslak
Radek Wyroslak

Reputation: 750

You need to use $scope.$apply() (or $rootScope.$digest()) and define then() before calling it. I've modified your example:

describe('promise', function(){
  jasmine.DEFAULT_TIMEOUT_INTERVAL = 500;
  let q;
  let scope;

  beforeEach(inject(function($q, $rootScope){
    q = $q;
    scope = $rootScope.$new();
  }));

  it('finishes', function(done){
    expect(q).toBeDefined();
    const promise = q.resolve();
    promise.then(
      () => done(),
      () => done.fail()
    );
    scope.$apply();
  });
});

Upvotes: 1

doge1ord
doge1ord

Reputation: 311

I hope this example could help you using $rootScope.$digest() (I know you already tried forcing digest already). Just ignore the type declarations (was written using typescript)

    var service: IService;
    var $rootScope: ng.IRootScopeService;
    var $q: ng.IQService;

    beforeEach(() => {
        angular.mock.module("app");
        angular.mock.inject((
            _$rootScope_: ng.IRootScopeService,
            _$q_: ng.IQService
        ) => {
            // Assign dependecies
            $q = _$q_;
            $rootScope = _$rootScope_;
        });

        // Initialize service
        service = new Service($q);
    });


    it("should call errorCallback", () => {
        let callback = {
            errorCallback: function (response: any) { /*empty function */ }
        };

        spyOn(callback, "errorCallback");

        service.connect(null)
            .catch(callback.errorCallback);

        // Trigger a digest on rootScope (needed for $q implementation) 
        $rootScope.$digest();

        expect(callback.errorCallback).toHaveBeenCalled();
    });

Upvotes: 2

Related Questions