Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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;
        }
    }
}]);
like image 953
Sam Avatar asked Oct 31 '13 23:10

Sam


People also ask

How do you test promise reject Jasmine?

describe('test promise with jasmine', function() { it('expects a rejected promise', function() { var promise = getRejectedPromise(); // return expect(promise). toBe('rejected'); return expect(promise. inspect(). state).

How do you test async on Jasmine?

If an operation is asynchronous just because it relies on setTimeout or other time-based behavior, a good way to test it is to use Jasmine's mock clock to make it run synchronously. This type of test can be easier to write and will run faster than an asynchronous test that actually waits for time to pass.

How do I test API calls in Jasmine?

Create a Mock API with Jasminejson file in your root directory. If not, you can set it up with this command: npm init -y . Your test should pass! Try changing the value of a to false, and running it again to see what it looks like when a test fails.


2 Answers

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

like image 72
redmallard Avatar answered Sep 28 '22 19:09

redmallard


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.)

like image 21
Bonneville Avatar answered Sep 28 '22 20:09

Bonneville