小编典典

在Angular中进行单元测试指令控制器而无需使控制器成为全局控制器

angularjs

在Vojta
Jina的优秀存储库中,他在其中演示了指令的测试,他在模块包装器之外定义了指令控制器。看到这里:https : //github.com/vojtajina/ng-
directive-testing/blob/master/js/tabs.js

这不是不好的做法并且会污染全局名称空间吗?

如果在另一个地方可以合理地调用TabsController,那会不会很麻烦?

可以在此处找到针对上述指令的测试:https : //github.com/vojtajina/ng-directive-
testing/commit/test-controller

是否可以将指令控制器与指令的其余部分分开测试,而无需将控制器放在全局命名空间中?

将整个指令封装在app.directive(…)定义中会很好。


阅读 216

收藏
2020-07-04

共1个答案

小编典典

很好的问题!

因此,这是一个普遍的关注点,不仅对于控制器而言,而且对于指令可能需要执行其工作但不一定要将该控制器/服务暴露给“外部世界”的服务而言,都是潜在的问题。

我坚信 全局数据是有害的,应避免使用,这也适用于指令控制器
。如果采用这种假设,我们可以采用几种不同的方法来“本地”定义那些控制器。在这样做的时候,我们需要记住, 控制器应该仍然可以“轻松”地用于单元测试,
因此我们不能简单地将其隐藏在指令的闭包中。IMO的可能性是:

1)首先,我们可以简单地 在模块级别上定义指令的控制器 ,例如:

angular.module('ui.bootstrap.tabs', [])
  .controller('TabsController', ['$scope', '$element', function($scope, $element) {
    ...
  }])
 .directive('tabs', function() {
  return {
    restrict: 'EA',
    transclude: true,
    scope: {},
    controller: 'TabsController',
    templateUrl: 'template/tabs/tabs.html',
    replace: true
  };
})

这是我们基于Vojta的工作在https://github.com/angular-
ui/bootstrap/blob/master/src/tabs/tabs.js中使用的一种简单技术。

尽管这是一种非常简单的技术,但应注意,控制器仍然暴露于整个应用程序中,这意味着其他模块可能会覆盖它。从这个意义上讲,它使控制器对于AngularJS应用程序是本地的(因此不会污染全局窗口范围),但对于所有AngularJS模块也是全局的。

2) 使用闭包范围和特殊文件设置进行测试

如果要完全隐藏控制器功能,可以将代码包装在闭包中。这是AngularJS使用的技术。例如,查看NgModelController,我们可以看到它在自己的文件中被定义为“全局”函数(因此可以轻松地进行测试),但是整个文件在构建期间都被封装在闭包中:

综上所述:选项(2)比较“安全”,但是需要一些先期的构建步骤。

2020-07-04