Angularjs 如何在控制器中测试角度元素绑定

Angularjs 如何在控制器中测试角度元素绑定,angularjs,jasmine,Angularjs,Jasmine,我有以下控制器 angular.module('jobBoard').controller('JobListController', ['$scope','$window', function($scope, $window){ $scope.keywordPlaceholder = 'What kind of job?'; $scope.locationPlaceholder = 'Where? (city, state or zip)'; $scope.onRe

我有以下控制器

 angular.module('jobBoard').controller('JobListController', ['$scope','$window', function($scope, $window){

    $scope.keywordPlaceholder = 'What kind of job?';
    $scope.locationPlaceholder = 'Where? (city, state or zip)';

    $scope.onResize = function(){
        if ($window.innerWidth <= 480){
            $scope.keywordPlaceholder = 'What?';
            $scope.locationPlaceholder = 'Where?';
        }
    }

    angular.element($window).bind('resize', function(){
        $scope.onResize();
        $scope.$apply();
    })

    $scope.onResize();
    $scope.loadJobs();
}]);

但是它在scope.onResize预期上失败了。我在谷歌上疯狂地搜索如何正确地做到这一点,但似乎找不到正确的答案。有什么想法吗?谢谢。

老实说,我从来没有试过这个,所以我不能告诉你它是否有效。但是,您将调用函数与触发事件混淆。您的
bind
语句绑定到事件,而不是函数调用

从中,您应该能够执行以下操作来创建一个名为“resize”的事件并触发它:

describe('binding resize to window', function(){
    // Get a DOM element (there's probably a better way to do this...)
    var mockWindow = angular.element('<div>')[0];
    // create the event
    var resizeEvent = new Event('resize');


    beforeEach(inject(function($rootScope, $controller){
        scope = $rootScope.$new();
        $controller('JobListController', { $scope:scope, $window: mockWindow});
    }))

    it('binds to the resize function', function(){
        spyOn(scope, 'onResize');
        spyOn(scope, '$apply');
        // call the event.
        mockWindow.dispatchEvent(event);
        expect(scope.onResize).toHaveBeenCalled();
        expect(scope.$apply).toHaveBeenCalled();
    })
})
descripe('binding resize to window',function(){
//获取一个DOM元素(可能有更好的方法来实现这一点…)
var mockWindow=angular.element(“”)[0];
//创建事件
var resizeEvent=新事件(“调整大小”);
beforeach(注入(函数($rootScope,$controller){
scope=$rootScope.$new();
$controller('JobListController',{$scope:scope,$window:mockWindow});
}))
它('绑定到resize函数',函数(){
spyOn(范围“onResize”);
spyOn(范围,$apply');
//打电话给这个活动。
mockWindow.dispatchEvent(事件);
expect(scope.onResize).toHaveBeenCalled();
expect(scope.$apply).tohavebeencall();
})
})

如果您想测试是否附加到事件,Angular的
$window
服务很好地满足了这一目的:

describe('JobListController', function(){
  var scope, controller;

  describe('binding resize to window', function(){
    beforeEach(inject(function($rootScope, $controller){
      scope = $rootScope.$new();
      spyOn($window, 'addEventListener').and.callThrough();
      $controller('JobListController', { $scope:scope });
    }))

    it('binds to the resize function', function() {
      expect($window.addEventListener).toHaveBeenCalledWith('resize', scope.onResize);
    })
  })
})
在控制器中,改为使用
addEventListener
绑定:

$window.addEventListener('resize', scope.onResize);
它还允许在您解除绑定事件时进行测试:

it('stop listening to window resize', function () {
    compileDirective();
    spyOn($window, 'removeEventListener');

    scope.$destroy();

    expect($window.removeEventListener).toHaveBeenCalledWith('resize', scope.onResize);
});
之后,您可以自由地独立测试
scope.onResize
逻辑

优点:

  • 容易做
  • 允许测试事件的解除绑定
  • 在任何浏览器中都能正常工作(即使是PhantomJS)
缺点:

  • 它不测试每个部分(事件、侦听器、处理程序)之间的交互。我依靠更高水平的测试(即:E2E)

谢谢。这在chrome上运行良好,但phantomjs抱怨新事件。显然这是phantomjs的一个问题。@geoffswartz:我发布了另一个在phantomjs中运行良好的解决方案。
it('stop listening to window resize', function () {
    compileDirective();
    spyOn($window, 'removeEventListener');

    scope.$destroy();

    expect($window.removeEventListener).toHaveBeenCalledWith('resize', scope.onResize);
});