Sam
Sam

Reputation: 15761

Testing an Angular Promise with Jasmine

The following test keeps failing and I can't figure out why? I am trying to figure out how to test defereds/promises with Jasmine.

Error

Expected undefined to be 'Resolved Data'.

Test

    describe('Queued Repository', function () {
    var ctrl,
        rootScope,
        scope,
        service;

    beforeEach(function () {
        module('testApp');

        inject(function ($rootScope, $controller, TestSrvc) {
            rootScope = $rootScope;
            scope = $rootScope.$new();
            service = TestSrvc;
        });
    });

    afterEach(inject(function ($rootScope) {
        $rootScope.$apply();
    }));

    it('test something', function () {
        expect(service.calculate(1, 5)).toBe(6);
    });

    it('resolves promises', function () {
        var result;

        service.getPromise().then(function (data) {
            result = data;
        });

        rootScope.$apply();
        expect(result).toBe('Resolved Data');
    });
});

Service

    var app = angular.module('testApp', []);

app.service('TestSrvc', ['$q', '$timeout', '$http', function ($q, $timeout, $http) {
    return {
        getPromise: function () {
            var d = $q.defer();

            $timeout(function () {
                d.resolve('Defered Result');
            }, 5000);

            return d.promise;
        },
        getSomething: function () {
            return "Test";
        },
        calculate: function (x, y) {
            return x + y;
        }
    }
}]);

Upvotes: 16

Views: 8558

Answers (2)

Bonneville
Bonneville

Reputation: 3583

In your example, you will need to call both $timeout.flush() AND $rootScope.$apply().

Explanation: $timeout.flush() will force your $timeout in the service to run immediately. Your service will then call 'resolve' - but the promise.then() will not be called until the subsequent digest cycle; therefore you will need to call $rootScope.$apply() to propagate any 'resolves' and 'watches' - which will occur synchronously.

NOTE: In Jasmine, ensure that your promise.then() function appears BEFORE your call to $rootScope.$apply otherwise it will not fire the promise.then() function. (I haven't figured out why this is the case in Jasmine.)

Upvotes: 3

redmallard
redmallard

Reputation: 1138

Try calling $timeout.flush() before expect(result).toBe('Resolved Data');.

Upvotes: 9

Related Questions