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(); });
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.
AngularJS also provides the ngMock module, which provides mocking for your tests. This is used to inject and mock AngularJS services within unit tests.
You need to inject $rootScope
in your test and trigger $digest
on it.
there is always the $rootScope, use it
inject(function($rootScope){ myRootScope=$rootScope; }) .... myRootScope.$digest();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With