我有myService使用myOtherService,它可以进行远程调用,并返回promise:
myService
myOtherService
angular.module('app.myService', ['app.myOtherService']) .factory('myService', [ myOtherService, function(myOtherService) { function makeRemoteCall() { return myOtherService.makeRemoteCallReturningPromise(); } return { makeRemoteCall: makeRemoteCall }; } ])
要对myService我进行单元测试,需要模拟myOtherService,以便其makeRemoteCallReturningPromise方法返回promise。这是我的方法:
makeRemoteCallReturningPromise
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'); }); }));
从上面可以看到,我的模拟的定义取决于$q,我必须使用来加载inject()。此外,应该在中进行注入模拟module(),这应该在之前进行inject()。但是,更改模拟后,其值不会更新。
$q
inject()
module()
正确的方法是什么?
我不确定为什么您的方法不起作用,但是我通常使用该spyOn函数来完成。像这样:
spyOn
describe('Testing remote call returning promise', function() { var myService; beforeEach(module('app.myService')); beforeEach(inject( function(_myService_, myOtherService, $q){ myService = _myService_; spyOn(myOtherService, "makeRemoteCallReturningPromise").and.callFake(function() { var deferred = $q.defer(); deferred.resolve('Remote call result'); return deferred.promise; }); } it('can do remote call', inject(function() { myService.makeRemoteCall() .then(function() { console.log('Success'); }); }));
还要记住,您将需要$digest调用要调用的then函数。请参阅$q文档的“ 测试”部分。
$digest
then
- - - 编辑 - - -
在仔细查看您在做什么之后,我认为我在您的代码中看到了问题。在中beforeEach,您将设置myOtherServiceMock为一个新对象。将$provide永远不会看到这个参考。您只需要更新现有参考:
beforeEach
myOtherServiceMock
$provide
beforeEach(inject( function(_myService_, $q){ myService = _myService_; myOtherServiceMock.makeRemoteCallReturningPromise = function() { var deferred = $q.defer(); deferred.resolve('Remote call result'); return deferred.promise; }; }