Jasmine:在AngularJS承诺中调用



我的AngularJS控制器中有以下功能:

service.getPlaceByAddress = function(address) {
return $q(function(resolve, reject) {
geocoder().geocode({'address': address}, function(result, status) {
// gets called
if (status === google.maps.GeocoderStatus.OK) {
return resolve(result);
}
return reject();
});
});
};

我想测试这段代码,但 then 函数不会被调用。但是地理编码函数肯定会被调用。

it('returns an error if the data service returns no results', function(done) {
GoogleMaps.getPlaceByAddress('Testlocation').then(function() {
done();
// gets never called
});
$scope.$digest();
});

相反,我得到一个异步超时:

错误:超时 - 在 Jasmine 指定的超时内未调用异步回调。DEFAULT_TIMEOUT_INTERVAL。

编辑

当我直接返回resolve时,它按预期工作:

service.getPlaceByAddress = function(address) {
return $q(function(resolve, reject) {
return resolve();
//geocoder()...
});
};

所以我认为,问题出在地理编码器的回调上。这很奇怪,因为代码在浏览器中运行良好,但在茉莉花测试中却不能......

我认为问题是您正在调用真正的异步服务,而不是在单元测试中将其简化。如果你有一个虚拟服务立即完成承诺,那么测试调用$scope.$digest()一次就足以触发then()回调,但如果它是一个真正的异步调用,则在远程服务器有机会实际发回任何数据之前,将调用摘要。

最好的解决方案是假掉测试的异步部分。因此,在此测试中,您将为geocoder().geocode()放置一个存根,当以TestLocation作为参数调用时,该存根只是立即成功完成或失败,或者对每个参数进行测试。

或者,你可以有一个循环,等到请求真正有机会完成,但这对于单元测试来说是不好的风格,因为它们应该是自包含的,而不是依赖于远程服务器。

从您的评论中:

您链接的博客文章向您展示了如何模拟对 geocoder 的调用,但在该博客文章中,它只是验证是否已调用地理编码器方法,它实际上并没有测试服务承诺是否已解决,并且使用的间谍只是返回一个值,它不会触发回调。

所以我认为你需要在他们所做的事情的基础上再接再厉:添加一个实际触发回调的间谍,但与承诺相关的所有内容都是异步的,所以你需要调用$digest()来强制承诺完成。

最新更新