Question

I'm using a service to share data between controllers. If a value on the service changes, I want to update some data binding on my controllers. To do this, I'm using $scope.$watchCollection (because the value I'm watching is a simple array). I'm having trouble trying to figure out how to test this in Jasmine + Karma.

Here is a simple Controller + Service setup similar to what I'm doing in my app (but very simplified):

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: []
  };
});

And here is a test case that I've attempted (but does not work):

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

});

I guess my question is twofold:

How do I properly mock the service that is used in the controller? How do I then test that the $watchCollection function is working properly?

Here is a plunkr for the above code. http://plnkr.co/edit/C1O2iO

Était-ce utile?

La solution

Your test (or your code ) is not correct .

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

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

and

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

or your expectation makes no sense

I strongly encourage you to lint your javascript (jslint/eslint/jshint) to spot stupid errors like the first one.Or you'll have a painfull experience in writing javascript. jslint would have detected that the variable you were using didnt exist in the scope.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top