【发布时间】:2014-07-05 11:36:08
【问题描述】:
我有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。我就是这样做的:
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');
});
}));
从上面可以看出,我的 mock 的定义取决于 $q,我必须使用 inject() 加载它。此外,注入模拟应该在module() 中进行,它应该在inject() 之前。但是,一旦我更改了模拟的值,它就不会更新。
这样做的正确方法是什么?
【问题讨论】:
-
myService.makeRemoteCall()上真的有错误吗?如果是这样,问题在于myService没有makeRemoteCall,与您的嘲笑myOtherService无关。 -
错误出现在 myService.makeRemoteCall() 上,因为此时 myService.myOtherService 只是一个空对象(其值从未被 angular 更新过)
-
您将空对象添加到 ioc 容器中,然后更改引用 myOtherServiceMock 以指向您监视的新对象。 ioc 容器中的内容不会反映这一点,因为引用已更改。
标签: javascript angularjs unit-testing mocking jasmine