I have a service named myService
that relies on another service called myOtherService
. The latter makes a remote call and returns a promise. Here's the implementation:
angular.module('app.myService', ['app.myOtherService'])
.factory('myService', [
myOtherService,
function(myOtherService) {
function makeRemoteCall() {
return myOtherService.makeRemoteCallReturningPromise();
}
return {
makeRemoteCall: makeRemoteCall
};
}
])
To create a unit test for myService
, I need to mock myOtherService
so that its method makeRemoteCallReturningPromise
returns a promise. This is how it can be done:
describe('Testing remote call returning promise', function() {
var myService;
var myOtherServiceMock = {};
beforeEach(module('app.myService'));
// The mock should be injected when calling module(),
// with module() placed before any inject()
beforeEach(module(function ($provide) {
$provide.value('myOtherService', myOtherServiceMock);
}));
// To properly construct the mock,
// $q is needed to create a promise
beforeEach(inject(function(_myService_, $q){
myService = _myService_;
myOtherServiceMock = {
makeRemoteCallReturningPromise: function() {
var deferred = $q.defer();
deferred.resolve('Remote call result');
return deferred.promise;
}
};
}
// However, the value of myOtherServiceMock remains {}
it('can perform a remote call', inject(function() {
myService.makeRemoteCall() // Error: makeRemoteCall() is not defined on {}
.then(function() {
console.log('Success');
});
}));
From the example above, it's clear that defining the mock relies on $q
, which is obtained through inject()
. Additionally, injecting the mock should happen within module()
before using inject()
. Unfortunately, updating the value of the mock does not reflect the changes.
What is the correct approach to handle this situation?