Mam myServiceto zastosowania myOtherService, które wykonuje zdalne połączenie, zwracając obietnicę:
angular.module('app.myService', ['app.myOtherService'])
.factory('myService', [
myOtherService,
function(myOtherService) {
function makeRemoteCall() {
return myOtherService.makeRemoteCallReturningPromise();
}
return {
makeRemoteCall: makeRemoteCall
};
}
])
Aby wykonać test jednostkowy myService, muszę mock myOtherService, tak aby jego makeRemoteCallReturningPromisemetoda zwracała obietnicę. Oto jak to robię:
describe('Testing remote call returning promise', function() {
var myService;
var myOtherServiceMock = {};
beforeEach(module('app.myService'));
// I have to inject mock when calling module(),
// and module() should come before any inject()
beforeEach(module(function ($provide) {
$provide.value('myOtherService', myOtherServiceMock);
}));
// However, in order to properly construct my mock
// I need $q, which can give me a promise
beforeEach(inject(function(_myService_, $q){
myService = _myService_;
myOtherServiceMock = {
makeRemoteCallReturningPromise: function() {
var deferred = $q.defer();
deferred.resolve('Remote call result');
return deferred.promise;
}
};
}
// Here the value of myOtherServiceMock is not
// updated, and it is still {}
it('can do remote call', inject(function() {
myService.makeRemoteCall() // Error: makeRemoteCall() is not defined on {}
.then(function() {
console.log('Success');
});
}));
Jak widać z powyższego, definicja mojej makiety zależy od tego $q, którą mam załadować za pomocą inject(). Co więcej, wstrzyknięcie makiety powinno mieć miejsce module(), co powinno nastąpić wcześniej inject(). Jednak wartość makiety nie jest aktualizowana po jej zmianie.
Jaki jest właściwy sposób, aby to zrobić?
myService.makeRemoteCall()? Jeśli tak, problem polega namyServicetymmakeRemoteCall, że nie masz nic wspólnego z wyśmiewanymmyOtherService.