如何测试监视注入服务的更改的控制器?

时间:2014-05-10 15:55:05

标签: angularjs jasmine karma-runner angularjs-service

我使用服务在控制器之间共享数据。如果服务上的值发生更改,我想更新控制器上的某些数据绑定。要做到这一点,我使用$ 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

1 个答案:

答案 0 :(得分: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会检测到您使用的变量在范围内不存在。