单元测试包含$ watch()未编译的AngularJS指令

时间:2013-12-30 10:47:25

标签: javascript unit-testing angularjs

我目前正在研究我的问题,但我认为在这里添加一个问题可能有所帮助,因为我是AngularJS的新手,甚至更新的单元测试。

我有当前的指令,它使用$watch()函数来跟踪变量,如果变量不存在则提供默认消息,例如“Deleted User Value”...

angular.module('myModule')


.directive('displayName', function ($transform) {
    return {
        restrict: 'A',
        scope: {
            displayName: '='
        },
        link: function (scope, element) {
            scope.$watch('displayName', function(value){
                if(!value) {
                    element.html($transform('users.profile.deletedUser'));
                } else {
                    element.html(value);
                }
            });
        }
    };
})

;

我有以下单元测试(请注意我已根据Maurice的建议对其进行了修改):

beforeEach(module('myModule'));

beforeEach(inject(function($compile, $rootScope) {
    $scope = $rootScope;
    element = angular.element('<div class="name" display-name="name"></div>');
    $compile(element)($scope);
}));


it('should display the deleted user name', inject(function() {
    $scope.displayName = null;
    element.scope().$apply();
    console.log(element);
    expect(element.html()).toBe('Deleted User Value');

}));

但是我收到了以下问题:TypeError: Attempted to assign to readonly property。并且console.log没有被输出,任何人都可以告诉我哪里出错了?对不起我的愚蠢,但我正在尝试“在工作中”学习单元测试,我仍然是AngularJS的新手

1 个答案:

答案 0 :(得分:7)

代码似乎有些问题。

该指令依赖于$translate,在使用$transform但未注入时不使用该指令。

其次在你的第二次测试中,你正在呼叫element.$scope().$apply();。那应该是element.scope().$apply();

最后,您要在范围上设置displayName属性,但使用name绑定到测试代码中的<div class="name" display-name="name"></div>属性。

我会写这样的测试:

describe("The displayName directive", function () {
    var $scope, element;

    beforeEach(module('myModule'));

    beforeEach(inject(function ($compile, $rootScope) {
        $scope = $rootScope;
        element = angular.element('<div class="name" display-name="name"></div>');
        $compile(element)($scope);
    }));

    it('should display the deleted user name', function () {
        element.scope().$apply();
        expect(element.text()).toBe('users.profile.deletedUser');

    });

    it('should display the actual user name', function () {
        $scope.name = "Maurice";
        element.scope().$apply();
        expect(element.text()).toBe('Maurice');
    });
});