如何在Karma测试中更改常量值

时间:2015-07-07 20:58:12

标签: javascript angularjs unit-testing karma-runner

我有一个Angular指令,它根据注入常量的值设置某些$scope属性的值。我想测试这个值是否从常量中正确初始化,所以我想在单个it块中更改常量值。 (最好在一个,但改变多个块之间的值也可以)

这可能,我该怎么做?

简化示例:

//////// directive ////////
angular.module('myApp.directives', [])
.constant('THE_CONSTANT', 'hello world')
.directive('myDirective', ['THE_CONSTANT', function (THE_CONSTANT) {

    return {
        restrict: 'E',
        link: function ($scope) {
            $scope.propertyBasedOnConstant = THE_CONSTANT;
        }
    };
}]);

//////// test ////////
describe('myDirective', function () {
    var $element, $scope;

    beforeEach(module('myApp.directives'));

    beforeEach(module(function ($provide) {
        $provide.constant('THE_CONSTANT', 'foo');
    }));

    beforeEach(inject(function ($rootScope, $compile) {
        $scope = $rootScope;
        $element = angular.element('<my-directive></my-directive>');
        $compile($element)($scope);
        $scope.$digest();
    }));

    afterEach(function () {
        $scope.$destroy();
        $element.remove();
    });

    it("should correctly reflect the constant's value", function() {
        expect( $scope.propertyBasedOnConstant ).to.equal('foo');

        // now I want to change the constant's value and re-initialize the directive
    });    
});

2 个答案:

答案 0 :(得分:4)

您正在将constant提供给undefined模块。

将您的beforeEach块更改为类似的内容应该正常工作

var $scope, $element, MOCKED_CONSTANT;

beforeEach(function () {
  MOCKED_CONSTANT = 'foo';

  module('myApp.directives', function ($provide) {
    $provide.constant('THE_CONSTANT', MOCKED_CONSTANT);
  });

  inject(function ($rootScope, $compile) {
    $scope       = $rootScope.$new(); // Don't forget to call .$new()!
    var template = angular.element('<my-directive></my-directive');
    $element     = $compile(template)($scope); // Store the reference to the compiled element, not the raw string.
    $scope.$digest();
  });
});

it("should correctly reflect the constant's value", function() {
  expect( $scope.propertyBasedOnConstant ).to.equal(MOCKED_CONSTANT);
  // expect( $scope.propertyBasedOnConstant ).to.equal('foo');
});

如果您需要更改it之间的常量值,我会将对module的调用解压缩为辅助函数,以及inject。如:

function setupModule (constant) {
  module('myApp.directives', function ($provide) {
    $provide.constant('THE_CONSTANT', constant);
  });
}

function injectItAll () {
  inject(function ($rootScope, $compile) {
    $scope       = $rootScope.$new(); // Don't forget to call .$new()!
    var template = angular.element('<my-directive></my-directive');
    $element     = $compile(template)($scope); // Store the reference to the compiled element, not the raw string.
    $scope.$digest();
  });
}

然后在您的规范中,您会这样做:

it('equals banana', function () {
  setupModule('banana');
  injectItAll();
  expect($scope.propertyBasedOnConstant).to.equal('banana');
});

答案 1 :(得分:1)

根据定义,常量是具有无法更改的关联值的标识符。而不是改变常数值,为什么不注入常数本身并在你的期望中使用它。

describe('myDirective', function () {
    var $element, $scope,
      THE_CONSTANT;

    beforeEach(module('myApp.directives'));

    beforeEach(module(function (_THE_CONSTANT_) {
      THE_CONSTANT = _THE_CONSTANT_;
    }));

    beforeEach(inject(function ($rootScope, $compile) {
        $scope = $rootScope;
        $element = angular.element('<my-directive></my-directive>');
        $compile($element)($scope);
        $scope.$digest();
    }));

    afterEach(function () {
        $scope.$destroy();
        $element.remove();
    });

    it("should correctly reflect the constant's value", function() {
        expect( $scope.propertyBasedOnConstant ).to.equal(THE_CONSTANT);
    });    
});