【问题标题】:Jasmine: Calling then in AngularJS PromiseJasmine:在 AngularJS Promise 中调用 then
【发布时间】:2017-03-27 07:23:08
【问题描述】:

我的 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 函数不会被调用。但是 geocode 函数肯定会被调用。

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()...
    });
};

所以我认为,问题出在地理编码器的回调中。这很奇怪,因为代码在浏览器中完美运行,但在 jasmine 测试中却不行……

【问题讨论】:

标签: javascript angularjs jasmine karma-jasmine


【解决方案1】:

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

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

或者,您可以有一个循环,等待请求真正有机会完成,但这对于单元测试来说是一种糟糕的风格,因为它们应该是独立的,而不是依赖于远程服务器。

来自您的评论:

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

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

【讨论】:

  • 谢谢。我认为您是对的,并且测试无法与真正的异步服务正常工作。正因为如此,我像下面的操作方法中所说的那样模拟了数据:kwilson.io/blog/… 但我曾经打电话给$scope.$digest(),这在操作方法中没有提到。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-24
  • 1970-01-01
  • 1970-01-01
  • 2021-04-16
相关资源
最近更新 更多