Reputation: 363
Below was my approach to testing rejected promises in angular 1.5.x. Updating to 1.6.1 has introduced the "Possibly unhandled rejection" error. I understand the purpose of this error, but I haven't figure out a simple way around it. Jasmine's (2.5.x) and.throwError() method seems to cause tests to fail by virtue of being an error.
describe('TestTarget', () => {
let $q, $rootScope, TestTarget, SomeModel;
beforeEach(() => {
SomeModel = jasmine.createSpyObj('SomeModel', ['get']);
module('something');
module($provide => {
$provide.value('SomeModel', SomeModel);
});
inject((_$q_, _$rootScope_, _TestTarget_) => {
$q = _$q_;
$rootScope = _$rootScope_;
TestTarget = _TestTarget_;
});
});
describe('get()', () => {
it('on error, adds a danger message', () => {
SomeModel.get.and.returnValue($q.reject());
// SomeModel.get.and.throwError(); // doesn't work either
TestTarget.get();
$rootScope.$digest();
expect(SomeModel.get).toHaveBeenCalled();
expect(<< the rejection outcome of TestTarget.get().then() >>);
});
});
});
I want to continue to pass rejected promises across my models, services, and controllers.
Upvotes: 2
Views: 2327
Reputation: 533
I had this issue with angular 1.6.1. Try callFake instead of returnValue in your test.
describe('TestTarget', () => {
let $q, $rootScope, TestTarget, SomeModel;
beforeEach(() => {
SomeModel = jasmine.createSpyObj('SomeModel', ['get']);
module('something');
module($provide => {
$provide.value('SomeModel', SomeModel);
});
inject((_$q_, _$rootScope_, _TestTarget_) => {
$q = _$q_;
$rootScope = _$rootScope_;
TestTarget = _TestTarget_;
});
});
describe('get()', () => {
it('on error, adds a danger message', () => {
SomeModel.get.and.callFake(() => $q.reject());
// SomeModel.get.and.throwError(); // doesn't work either
TestTarget.get();
$rootScope.$digest();
expect(SomeModel.get).toHaveBeenCalled();
expect(<< the rejection outcome of TestTarget.get().then() >>);
});
});
});
Upvotes: 0
Reputation: 1380
Let us say your actual code is like this:
angular.module('myApp').service('TestTarget', ['SomeModel', function(SomeModel) {
this.get = function() {
return SomeModel.get();
}
}]);
My assumption is you have no .catch
block chained to the returning Promise.
In this case you can simply test it like this:
it('on error, adds a danger message', () => {
SomeModel.get.and.returnValue($q.reject('some error'));
TestTarget.get()
.then(function() {
fail('the promise should not have been resolved');
}).catch(function(err) {
expect(err).toBe('some error');
});
$rootScope.$digest();
expect(SomeModel.get).toHaveBeenCalled();
});
Notice that I add a catch block to my function call. The $rootScope.$digest()
makes sure that the promise is resolved and all its chained then
and catch
blocks are getting called.
Upvotes: 3