【问题标题】:Unit testing Angular directive expression attribute which passes promises单元测试通过承诺的Angular指令表达式属性
【发布时间】:2016-12-18 14:37:25
【问题描述】:

我花了很多时间尝试对在控制器中生成/跟踪承诺的指令进行单元测试,可以在此处查看如何完成此操作的示例: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,但似乎没有任何东西可以完成承诺。

【问题讨论】:

  • 我是一个角度n00b,有没有办法将指令注入测试并直接调用link 方法,或者您是否必须编译和消化它才能对其进行评估?
  • 对于最低限度可行的测试,是否可以从saveCtrl 中删除 $timeout,以便立即解决承诺?并通过不使用随机来消除测试中的不确定性?理想情况下,可以有 2 个单独的测试一个 reject 分支和一个 resolve 分支?
  • @dm03514 当然,我将它添加到实际指令的功能中以重新创建异步调用,您可以完全消除超时并立即解决/拒绝。调用link 方法的唯一好方法是通过这些编译指令,但您始终可以将可测试的功能拆分为单独的controller

标签: javascript angularjs unit-testing jasmine


【解决方案1】:

我想我明白了。 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 行有一个未定义的 var,角度超时的行为很奇怪。这应该会导致使用超时测试保存的指令的完整流程。我认为可能不需要超时,但是您可以假设即时超时情况而不会丢失任何测试。

【讨论】:

  • 哈哈,我从没想到会在模拟承诺中添加额外的摘要,疯了!
猜你喜欢
  • 2016-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多