2016-11-15 6 views
0

Ну, я потратил день или около того, чтобы найти решения для этого, и я не знаю, что я более мудрый, поэтому я сломался и решил спросить , Кроме того, я довольно новичок в угловатости, поэтому терпение ценится.

У меня есть служба, которая периодически вызывается из контроллера для получения обновленных оценок суждений с удаленного сервера. Довольно стандартный материал. Только соответствующий код показан - без обработчиков ошибок и интервала отмены и т.д.

$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() службы с каждой проверенной итерацией? Я пробовал разные вещи, все без успеха:

  • Созданный отложенный, который сам возвратил отложенное обещание. Таким образом безумие.
  • Попытка повторно установить httpBackend.whenGET() с новым ответом. Это не имело никакого эффекта.
  • Создал новый отложенный внутри теста между интервальными итерациями. Излишне говорить, что это не удалось, поскольку первоначальное обещание отложенного уже было создано.
  • Возвращает статическое значение fromGET() и напрямую обрабатывает это значение. К сожалению, хотя это «работает», оно кажется довольно хакерским и вызвало другое испытание (которое ожидает отклонения).

Так что же мне не хватает? В чем тут трюк? Я открыт альтернативным решениям (не используя отложенные), а также все, что позволит очистить весы от моих глаз с помощью кода как есть.

ответ

0

Не слишком уверен в этом, но никто еще не ответил.

Стратегия:

  • определяют data массив с один фиктивный набор данных для каждого элемента массива.
  • использовать шаблон data.reduce(), чтобы протестировать каждый макет данных в последовательности async.
  • накапливает результаты в массиве по мере продвижения последовательности.
  • асинхронно выполнять одиночный 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% правильно, но может стимулировать дальнейшие идеи.