我有myService使用myOtherService,它进行远程调用,返回promise:
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()
之前发生 . 但是,一旦我更改了mock的值,就不会更新它 .
这样做的正确方法是什么?
8 回答
您可以使用像sinon这样的存根库来模拟您的服务 . 然后,您可以返回$ q.when()作为您的承诺 . 如果scope对象的值来自promise结果,则需要调用scope . $ root . $ digest() .
我们也可以直接通过 Spy 编写茉莉花实现的回复承诺 .
对于Jasmine 2:
(复制自评论,感谢ccnokes)
使用
sinon
:众所周知,
httpPromise
可以是:老实说..你依靠注入来模拟服务而不是模块,这是错误的做法 . 另外,在beforeEach中调用inject是一种反模式,因为它使得模拟在每个测试的基础上变得困难 .
以下是我将如何做到这一点......
现在,当您注入服务时,它将具有正确模拟的使用方法 .
我发现有用的,刺穿服务函数为sinon.stub() . returns($ q.when({})):
控制器:
并测试
代码段:
可以用更简洁的形式编写:
我'm not sure why the way you did it doesn'工作,但我通常使用
spyOn
函数 . 像这样的东西:还要记住,您需要调用
$digest
来调用then
函数 . 请参阅$q documentation的 Testing 部分 .------EDIT------
仔细看看你正在做什么之后,我想我在你的代码中看到了问题 . 在
beforeEach
中,您将myOtherServiceMock
设置为一个全新的对象 .$provide
永远不会看到这个参考 . 您只需要更新现有的参考: