AngularJS + Jasmine - 在指令中获取控制器范围

时间:2014-07-11 19:42:52

标签: javascript angularjs controller jasmine directive

我是AngularJS单元测试中的新手,我在测试一个用指令编写的控制器方法时遇到了一些麻烦。

这是我的 directive.js

app.directive('formLogin', ['AuthService', function(AuthService){
    return {
        restrict: 'E',
        templateUrl: utils.baseUrl + 'partials/_home-form-login.html',
        replace: true,
        controller: function ($scope, $element, $http, $location) {
            $scope.visible = false;
            $scope.showForm = function () {
                $scope.visible = !$scope.visible;
            };
        }
    };
}]);

这是我的 unit-test.js

describe('formLogin ctrl', function () {
    var element, scope, compile;

    beforeEach(module('Application'));

    beforeEach(inject(function ($rootScope, $compile) {
        element = angular.element('<form-login></form-login>');
        scope = $rootScope.$new();
        compile = $compile(element)($scope);       
    }));

    it('Test', function() {
        expect(scope.visible).toBe(false);
    })
});

通过这样做,“scope.visible”变为未定义。

有一些方法可以从我的控制器中获取$ scope,在“scope”变量中假设“visible”属性和“showForm”方法?

3 个答案:

答案 0 :(得分:2)

来自this link  看起来您可能需要执行scope.$digest();

答案 1 :(得分:2)

您似乎遇到了一些问题:

  1. compile = $compile(element)($scope); - 此处$scope未定义。它应该是compile = $compile(element)(scope);
  2. 正如smk所提到的,您需要消化范围以完成指令创建过程
    • 这一点尤其重要,因为您使用的是templateUrl。当你只使用本地定义的template时,正如Krzysztof在他的例子中所做的那样,你可以跳过这一步。
  3. 您可能会注意到,当您添加scope.$digest()时,您会遇到有关意外GET请求的其他问题。这是因为Angular正在尝试获取templateUrl,并且在测试期间必须手动配置/预期所有HTTP请求。您可能想要注入$httpBackend并执行$httpBackend.whenGet(/partials\//).respond('<div/>');之类的操作,但最终会遇到问题。

    更好的方法是注入模板$templateCache - Karma有一个预处理器为您执行此操作,或者您可以手动执行此操作。您可以阅读其他StackOverflow问题,like this one

    我已修改您的示例,以便在$templateCache中手动插入一个简单的模板,作为一个简单示例in this plunkr

    你应该看一下Karma的html2js预处理器,看看它是否能为你完成这项工作。

答案 2 :(得分:0)

如果您的指令没有隔离范围,您可以从指令控制器调用方法并测试它对范围值的影响。

describe('myApp', function () {
    var scope
      , element
    ;

    beforeEach(function () {
        module('myApp');
    });

    describe('Directive: formLogin', function () {
        beforeEach(inject(function ($rootScope, $compile) {
            scope = $rootScope.$new();
            element = angular.element('<form-login></form-login>');
            $compile(element)(scope);
        }));

        it('.showForm() – changes value of $scope.visible', function() {
            expect(scope.visible).toBe(false);
            scope.showForm();
            expect(scope.visible).toBe(true);
        });
    });
});

jsfiddle:http://jsfiddle.net/krzysztof_safjanowski/L2rBV/1/