0

I have a service 'dbService' written in angular.

devlog.service('dbService', ['$q', function($q) {

    this.getLogs = function() {
        var deferred = $q.defer();

        db.find({}, function(err, docs) {
            if(!err) {
                deferred.resolve(docs);
            } else {
                deferred.reject(err);
            }
        });

        return deferred.promise;
    }
}

The above code fetches data from database(nedb). Its just a wrapper around nedb's api, which returns a promise.

The idea of unit testing, is to test the logic without making any xhr or db calls.

How do i do that here, in my case ?

I've tried testing in the following way, assuming we are breaking the above law of separation of concerns.

describe("DevLog Services", function() {
    var dbService;
    var $rootScope;

    beforeEach(module('devLog'));

    beforeEach(inject(function(_$rootScope_, _dbService_) {
        $rootScope = _$rootScope_;
        dbService = _dbService_;
    }));

    it('should work', function(done) {
        var promise = dbService.getLogs();

        promise.then(function(logs) {
            console.log('yipee' + logs);
            expect(logs).toBeDefined();
        });

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

The above code doesn't resolve the promise.

I have tried out, adding an afterEach which does $rootScope.$apply();

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

    it('should work', function(done) {
        var promise = dbService.getLogs();
        var allLogs;

        promise.then(function(logs) {
            allLogs = logs;
            console.log(allLogs);
            done();
        });

        $rootScope.$apply();
        expect(allLogs).toBeDefined();

    });

In this case, i am getting this error Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL..

At least in this case, promise is getting resolved. But it is resolved after that test case is complete, which is causing the test case to fail.

Any ideas, how to resolve this

Solution:

I found the solution for this. The trick is to use $rootScope.$apply() in the service itself.

 devlog.service('dbService', ['$q', '$rootScope', function($q, $rootScope) {

    this.getLogs = function() {
        var deferred = $q.defer();

        db.find({}, function(err, docs) {
            if(!err) {
                deferred.resolve(docs);
            } else {
                deferred.reject(err);
            }

            $rootScope.$apply();
        });

        return deferred.promise;
    }
}

and in tests

it('should work', function(done) {
    var promise = dbService.getLogs();
    var allLogs;
    promise.then(function(logs) {
        expect(logs).toBeDefined();
        expect(logs.length).toBeGreaterThan(0);
        done();
    });

});
Dineshs91
  • 2,044
  • 1
  • 25
  • 24

0 Answers0