Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to resolve promises in AngularJS, Jasmine 2.0 when there is no $scope to force a digest?

It seems that promises do not resolve in Angular/Jasmine tests unless you force a $scope.$digest(). This is silly IMO but fine, I have that working where applicable (controllers).

The situation I'm in now is I have a service which could care less about any scopes in the application, all it does it return some data from the server but the promise doesn't seem to be resolving.

app.service('myService', function($q) {   return {     getSomething: function() {       var deferred = $q.defer();       deferred.resolve('test');       return deferred.promise;     }   } }); 

describe('Method: getSomething', function() {   // In this case the expect()s are never executed   it('should get something', function(done) {     var promise = myService.getSomething();      promise.then(function(resp) {       expect(resp).toBe('test');             expect(1).toEqual(2);     });      done();   });    // This throws an error because done() is never called.   // Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.   it('should get something', function(done) {     var promise = myService.getSomething();      promise.then(function(resp) {       expect(resp).toBe('test');             expect(1).toEqual(2);       done();     });   }); }); 

What is the correct way to test this functionality?

Edit: Solution for reference. Apparently you are forced to inject and digest the $rootScope even if the service is not using it.

  it('should get something', function($rootScope, done) {     var promise = myService.getSomething();      promise.then(function(resp) {       expect(resp).toBe('test');           });      $rootScope.$digest();     done();   });  
like image 865
Terry Avatar asked Jun 03 '14 17:06

Terry


People also ask

What is Q defer () in AngularJS?

Simply put you can use $q. defer() to create a Promise. A Promise is a function that returns a single value or error in the future. So whenever you have some asynchronous process that should return a value or an error, you can use $q. defer() to create a new Promise.

Which component is used to inject and mock AngularJS service within the unit test?

AngularJS also provides the ngMock module, which provides mocking for your tests. This is used to inject and mock AngularJS services within unit tests.


2 Answers

You need to inject $rootScope in your test and trigger $digest on it.

like image 72
pkozlowski.opensource Avatar answered Sep 24 '22 05:09

pkozlowski.opensource


there is always the $rootScope, use it

inject(function($rootScope){ myRootScope=$rootScope; }) ....  myRootScope.$digest(); 
like image 34
mpm Avatar answered Sep 21 '22 05:09

mpm