Angular测试多次调用通过$ inject with deferred

时间:2016-11-15 16:13:36

标签: angularjs testing jasmine deferred inject

我已经花了一天左右的时间寻找解决方案,而且我不知道我是谁更聪明,所以我已经崩溃并决定问。另外,我对棱角分明是相当新的,所以我很感激耐心。

我有一个定期从控制器调用的服务,用于从远程服务器检索更新的判断分数。相当标准的东西。仅显示相关代码 - 没有错误处理程序和间隔取消等。

 $app.service('ResultService', function($http) {
        var self = this;
        self.results = {};

        self.getResults = function() {

            return $http.get('/results').then(function(response) {
                return $q.when(response.data).then(function(data) {
                    angular.copy(self.results, response.data);
                };
            };

        };
    });

    $app.controller('ResultController', function($interval, resultService) {
        var vm = this;

        $interval(function() {
            resultService.getResults().then(function(data) {
                vm.results = data;
            });
        }, 1000);
    });

到目前为止一切顺利,一切都在浏览器中按预期工作。

现在进行测试。我想验证getResults函数是否收到并处理了更新,但是我正在努力执行必要的鸡祭,导致延期使用不止一次。我以为我可以这样做:

var deferred;
beforeEach(inject(function($q, httpBackend) {
    deferred = $q.defer();
    httpBackend.whenGET('/results').respond(deferred.promise);
});

it('updates results', inject(function($interval) {
    deferred.resolve({some: 'data'});
    scope.$digest();
    httpBackend.flush();
    $interval.flush(1200);
    // This works fine
    expect(resultsService.results).toEqual({some: 'data'});

    deferred.resolve({other: 'data'});
    scope.$digest();
    httpBackend.flush();
    $interval.flush(1200);
    // But this of course does not.
    expect(resultsService.results).toEqual({other: 'data'}); // fails
});

现在看来,延期的承诺只能解决一次。所以我的问题是,如何在每次测试的迭代中为服务的$ http.get()调用提供新数据?我尝试了各种各样的事情,都没有成功:

  • 创建了一个deferred,它本身返回了一个延迟的promise。这种疯狂就是这样。
  • 尝试使用新响应重新设置httpBackend.whenGET()。这没有效果。
  • 在间隔迭代之间在测试中创建了一个新的延迟。毋庸置疑,这是失败的,因为最初的延期承诺已经建立。
  • 从whenGET()返回一个静态值,并直接操作该值。不幸的是,虽然这个"工作",但它似乎相当hackish,并导致另一个测试(一个期望拒绝的测试)失败。

那我错过了什么?这里的诀窍是什么?我可以使用替代解决方案(不使用延迟)以及任何可以使用代码按原样清除我眼睛的比例的内容。

1 个答案:

答案 0 :(得分:0)

对此不太确定,但还没有其他人回复。

策略:

  • 定义一个data数组,每个数组元素有一个模拟数据集。
  • 利用data.reduce()模式测试异步序列中的每个模拟数据集。
  • 随着序列的进展在数组中累积结果。
  • 在收集所有结果时异步执行单个expect() - 应该等于原始data数组。
it('updates results', inject(function($interval) {
    var dataArray = [
        {some: 'data'},
        {other: 'data'}
    ]
    data.reduce(function(promise, data) {
        return promise.then(function(resultsArray) {
            // *** not sure about this section - I just copied and pasted ***
            deferred.resolve(data);
            scope.$digest();
            httpBackend.flush();
            $interval.flush(1200);
            // *** ****************************************************** ***
            return resultsArray.concat(resultsService.results);
        });
    }, deferred.resolve([])) // starter promise resolved with an empty results array.
    .then(function(results) {
        expect(results).toEqual(dataArray);
    });
});

很可能不是100%正确但可能会激发更多想法。