【问题标题】:Angular test multiple calls via $inject with deferred通过 $inject 延迟测试多个调用
【发布时间】:2016-11-15 16:13:35
【问题描述】:

好吧,我花了一天左右的时间寻找解决方案,但我不知道我是否更聪明,所以我崩溃了,决定问一下。另外,我对 Angular 还很陌生,因此请耐心等待。

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

 $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
});

现在看来,deferred 的 promise 只能解决一次。所以我的问题是,如何在每次测试迭代时为服务的 $http.get() 调用提供新数据?我尝试了各种方法,但都没有成功:

  • 创建了一个本身返回一个延迟承诺的延迟。如此疯狂。
  • 尝试使用新响应重新设置 httpBackend.whenGET()。这没有效果。
  • 在间隔迭代之间的测试内创建了一个新的 deferred。不用说这失败了,因为原来 deferred 的 promise 已经设置好了。
  • 从 whenGET() 返回一个静态值,并直接操作该值。不幸的是,虽然这“有效”,但它看起来相当老套,并导致另一项测试(预期会被拒绝)失败。

那么我错过了什么?这里有什么诀窍?我对替代解决方案(不使用延迟)以及任何可以使用代码原样清除我眼中的刻度的东西持开放态度。

【问题讨论】:

    标签: angularjs testing jasmine deferred inject


    【解决方案1】:

    对此不太确定,但尚未有其他人回复。

    策略:

    • 定义一个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% 正确,但可能会激发更多的想法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-12
      • 1970-01-01
      • 2018-03-25
      • 1970-01-01
      • 1970-01-01
      • 2018-09-19
      • 2021-12-07
      • 2019-09-16
      相关资源
      最近更新 更多