我正在尝试对Angular.js服务进行单元测试,并且需要对从Mock服务返回的promise(使用Jasmine)设置一个期望值。我正在使用业力单元测试框架。相关的代码段如下:
// I can't figure out how to do the equivalent of a $scope.$digest here.
var loginStatusPromise = FacebookService.getFacebookToken();
loginStatusPromise.then(function(token) {
expect(false).toBeTruthy(); // If this test passes, there is something going wrong!
expect(token).not.toBeNull(); // The token should be ValidToken
expect(token).toBe('ValidToken');
});
可以看到完整的单元测试代码here。
问题是promise.then语句在执行karma时永远不会触发。因此,我的期望陈述都没有被执行。 在我的控制器测试中,我使用$ scope。$ digest()来解决承诺,但我不清楚在服务测试中如何做到这一点。我认为在服务测试中没有“范围”的概念。
我在这里有错误的结尾吗?我是否需要将$ rootScope注入我的服务测试,然后使用$ digest?或者,还有另一种方式吗?
答案 0 :(得分:7)
我有这个问题并通过简单地放一个来解决它
在我的测试结束时$rootScope.$apply()
你的FacebookService可能是问题所在,正如@mpm所建议的那样。你确定它在Facebook
依赖关系中没有发生任何http调用,而这些调用在单元测试期间不会发生吗?你确定已经推迟了resolve
吗?
答案 1 :(得分:2)
假设您在解决方案/想法之前使用ngFacebook/ngModule快速说明该项目没有单元测试!您确定要使用此项目吗?
我在Github上快速扫描了你的单元测试,发现以下缺失: -
1)模块初始化。 ngFacebook需要你或者你需要初始化你做同样事情的模块。
beforeEach(module('ngFacebook'));
OR
beforeEach(module('yieldtome'));
2)认真考虑模仿ngFacebook模块
在单元级别测试中,您正在模拟气泡中测试代码,其中外部接口被删除。
否则)尝试添加调用API,如下所示: -
$rootScope.$apply(function() {
this.FacebookService.getFacebookToken().then(function(){
//your expect code here
});
});
$httpBackend.flush();//mock any anticipated outgoing requests as per [$httpBackend][2]
答案 2 :(得分:1)
beforeEach(function(){
var self=this;
inject(function($rootScope,Facebook){
self.$rootScope=$rootScope;
self.Facebook=Facebook;
});
})
it('resolves unless sourcecode broken',function(done){
// I can't figure out how to do the equivalent of a $scope.$digest here.
var loginStatusPromise = this.FacebookService.getFacebookToken();
loginStatusPromise.then(function(token) {
expect(token).toBe('ValidToken');
done();
});
$rootscope.$apply();
});
答案 3 :(得分:0)
我同意上述答案,即服务应该与$rootScope
无关。
在我的情况下有一个$q
承诺,它使用了第二个服务在内部解析承诺。无法解决外部问题,除非我将$rootScope.$digest()
添加到我的服务代码中(而非测试)......
我最终写了$q
这个快速垫片用于我的测试,但要小心,因为它只是一个例子,而不是一个完整的$q
实现。
beforeEach(module(function($provide) {
$provide.value('$q', {
defer: function() {
var _resolve, _reject;
return {
promise: {
then: function (resolve, reject) {
_resolve = resolve;
_reject = reject;
}
},
resolve: function (data) {
window.setTimeout(_resolve, 0, data);
},
reject: function (data) {
window.setTimeout(_reject, 0, data);
}
};
}
});
}));
希望它对某人有用,或者如果您有任何反馈。
感谢。