Как протестировать контроллер, который отслеживает изменения в внедряемом сервисе?

Я использую службу для обмена данными между контроллерами. Если значение службы изменится, я хочу обновить привязку некоторых данных к своим контроллерам. Для этого я использую $scope.$watchCollection (поскольку значение, которое я отслеживаю, представляет собой простой массив). У меня возникли проблемы с попыткой выяснить, как проверить это в Jasmine + Karma.

Вот простая настройка Controller + Service, аналогичная тому, что я делаю в своем приложении (но очень упрощенная):

var app = angular.module('myApp', []);

// A Controller that depends on 'someService'
app.controller('MainCtrl', function($scope, someService) {
  $scope.hasStuff = false;

  // Watch someService.someValues for changes and do stuff.
  $scope.$watchCollection(function(){
    return someService.someValues;
  }, function (){
    if(someService.someValues.length > 0){
      $scope.hasStuff = false;
    } else {
      $scope.hasStuff = true;  
    }

  });
});

// A simple service potentially used in many controllers
app.factory('someService', function ($timeout, $q){
  return {
    someValues: []
  };
});

И вот тестовый пример, который я пытался (но не работает):

describe('Testing a controller and service', function() {
  var $scope, ctrl;
  var mockSomeService = {
    someValues : []
  };

  beforeEach(function (){
    module('myApp');

    inject(function($rootScope, $controller) {
      $scope = $rootScope.$new();

      ctrl = $controller('MainCtrl', {
        $scope: $scope,
        someService: mockSomeService
      });
    });
  });

  it('should update hasStuff when someService.someValues is changed', function (){
    expect($scope.hasStuff).toEqual(false);

    // Add an item to someService.someValues
    someService.someValues.push(1);

    //$apply the change to trigger the $watch.
    $scope.$apply();

    //assert
    expect($scope.hasStuff).toEqual(true);
  });

});

Я думаю, мой вопрос двоякий:

Как правильно издеваться над службой, используемой в контроллере? Как проверить правильность работы функции $watchCollection?

Вот plunkr для приведенного выше кода. http://plnkr.co/edit/C1O2iO


person eterps    schedule 10.05.2014    source источник


Ответы (1)


Ваш тест (или ваш код) неверен.

http://plnkr.co/edit/uhSdk6hvcHI2cWKBgj1y?p=preview

mockSomeService.someValues.push(1); // instead of   someService.someValues.push(1);

а также

   if(someService.someValues.length > 0){
      $scope.hasStuff = true;
    } else {
      $scope.hasStuff = false;  
    }

или ваше ожидание не имеет смысла

Я настоятельно рекомендую вам проверить свой javascript (jslint/eslint/jshint), чтобы обнаружить глупые ошибки, такие как первая. Или у вас будет болезненный опыт написания javascript. jslint обнаружил бы, что используемая вами переменная не существует в области видимости.

person mpm    schedule 10.05.2014
comment
Да, я видел ошибку, но не знал, что с ней делать (поэтому я спрашиваю о переполнении стека). Думаю, я не осознавал, что изменение mockSomeService в тесте вызовет $change.$watchCollection. - person eterps; 10.05.2014