单元测试传递承诺的Angular指令表达式属性

Unit testing Angular directive expression attribute which passes promises

本文关键字:指令 指令表 表达式 属性 Angular 承诺 单元测试      更新时间:2023-09-26

我花了很多时间试图对一个在控制器中生成/跟踪承诺的指令进行单元测试,这里可以看到一个如何完成的例子:https://plnkr.co/edit/d8wMq0qlpiE4P25q5lhB

指令:

.directive('testDirective', function() {
    return {
        scope: {
            save: '&',
        },
        template: '<div><a href="#" ng-click="handleSave($event)">Click Here</a></div>',
        link: function(scope, element, attr, controllers) {
            scope.someData = {
                saving: false
            };
            scope.handleSave = function() {
                scope.someData.name = parseInt(Math.random() * 100);
                scope.someData.saving = true;
                scope.someData.error = false;
                scope.someData.id = null;
                return scope.save()(scope.someData)
                    .then(function(data) {
                        scope.someData = data;
                    })
                    .catch(function(err) {
                        scope.someData.error = true;
                    })
                    .finally(function() {
                        scope.someData.saving = false;
                    });
            };
        }
    };
})

控制器:

.controller('TestCtrl', function($scope, $q, $timeout) {
    $scope.saveCtrl = function(directiveData) {
        return $q(function(resolve, reject) {
            $timeout(function() {
                if (Math.round(Math.random())) {
                    directiveData.id = parseInt(Math.random() * 100);
                    resolve(directiveData);
                } else {
                    reject(new Error());
                }
            }, 2000)
        });
    }
});

模板:

<test-directive save="saveCtrl"></test-directive>

如示例中所示,它作为组件起作用,但是测试无法完成,因为.finally()从未被调用。我尝试了很多变体来强制使用$digest,但似乎没有一个能完成这个承诺。

我想我明白了。https://plnkr.co/edit/CBvrZo4g9LjJC61VV0wp

' ' '

$scope.saveCtrl = function(data) {
    return $q(function(resolve, reject) {
        setTimeout(function() {
            if (Math.round(Math.random())) {
                var id = parseInt(Math.random() * 100);
                resolve(id);
            } else {
                reject(new Error());
            }
            elementScope.$apply();
            $scope.$apply();
        }, 100);
   });
};

' ' '

在第39行有一个未定义的变量,并且角超时的行为很奇怪。这将导致使用超时来测试完整的指令流。我认为超时可能不需要,但你可以假设即时超时的情况下,没有任何测试损失。