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

时间:2015-03-05 21:57:52

标签: 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.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();
}]);

这是茉莉花的测试...

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

    describe('binding resize to window', function(){
        var mockWindow = {
            resize: function(){}
        }

        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');
            mockWindow.resize();
            expect(scope.onResize).toHaveBeenCalled();
            expect(scope.$apply).toHaveBeenCalled();
        })
    })
})

但是它在scope.onResize期望上失败了。我已经疯狂地搜索了如何正确地做到这一点,但似乎无法找到正确的答案。有任何想法吗?感谢。

2 个答案:

答案 0 :(得分:1)

说实话,我从未尝试过这个,所以我不能告诉你它是否会起作用。但是 - 你在调用一个触发事件的函数时会感到困惑。您的bind语句绑定到事件,而不是函数调用。

the MDN docs on javascript events开始,您应该可以执行以下操作来创建名为“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();
    })
})

答案 1 :(得分:0)

如果你想测试你附加到事件,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)。