使用sinon对角度控制器构造中调用的范围方法进行存根

时间:2015-09-17 15:56:51

标签: javascript angularjs unit-testing jasmine sinon

我有一个控制器,在构造时调用附加到$scope的方法:

angular.module('example', []).controller('exampleCtrl', function($scope) {
    $scope.method = function () { ... };

    $scope.method();
});

我想测试一下,在构造控制器的过程中,会调用此方法。我使用jasmine作为我的测试框架,使用sinon.js作为我的模拟框架。

describe('tests', function() {
    var $scope, $controller;

    beforeEach(inject(function($rootScope, _$controller_) {
        $scope = $rootScope.$new();
        $controller = _$controller_;
    });

    describe('During construction', function() {
        it('should call "method"', function() {
            $controller('exampleCtrl', { $scope: $scope });

            var methodStub = sinon.stub($scope, 'method');

            expect(methodStub.called).toBe(true);
        });
    });
});

这会失败,因为一旦$controller()被调用,它就会在我能够将它存根之前立即调用$scope.method()。但是,如果我尝试在构造之前存根该方法,

it('should call "method"', function() {
    var methodStub = sinon.stub($scope, 'method');

    $controller('exampleCtrl', { $scope: $scope });

    expect(methodStub.called).toBe(true);
});

sinon抛出一个错误:TypeError: Cannot read property 'restore' of undefined,因为$ scope.method没有定义,因为我还没有调用构造函数!

我还尝试直接在$scope上删除该方法,即$scope.method = sinon.stub(),但在控制器构建期间会被覆盖。

那么,是否可以存根构造期间调用的方法?

1 个答案:

答案 0 :(得分:1)

它不起作用,因为控制器总是覆盖你的存根。

这是一个干净的代码问题。

首先,控制器不应包含任何复杂的逻辑。通常它会进行测试,以便您模拟依赖项并检查它们是否被正确调用。

其次,首选控制器表示法是“controller as”。因此,Controller是一个经典的JS类。如果在原型中定义方法,则可以模拟/存根。

但总的来说,要求有点不寻常,可能表明控制器太过分了。