AngularJS-单元测试匿名控制器

时间:2014-10-24 15:01:58

标签: angularjs unit-testing angular-ui-router

我正在尝试为我编写的使用 ui-router 编写的代码编写测试。

我无法找到一种方法将控制器注入我的测试,因为它是在另一个控制器中配置的状态内内联和匿名编写的:

$scope.deleteSomething = function() {
  $modal.open(
    templateUrl: '/delete-item-modal.html',
    controller: ['$scope', '$modalInstance', 'someService', 
      function($scope, $modalInstance, someService) {
        ....
      }
    ],
    resolve: {
      ...
    }
  });  
};

如果控制器的名称类似于controller: 'TheController',那么在我的测试中通过这样做注入它会没有问题:

beforeEach(inject(function($controller) {
  $controller('TheController', {/*dependancies to be injected*/});
}));

但由于控制器是匿名的,我没有处理它,也无法弄清楚如何访问它。

2 个答案:

答案 0 :(得分:0)

这是一个站不住脚的情况。您应该对您准备修改的代码进行单元测试,以防止出现回归。如果您无法在当前状态下对其进行单元测试,那么您唯一的选择就是对其进行集成测试。 向请求工作的人解释:

  • 您必须在修改代码之前为代码编写测试。
  • 集成测试需要更长时间,但由于代码结构的原因,这是唯一可行的。
  • 通过提取命名控制器进行重构是一种复制粘贴和低风险。
  • 命名控制器可以轻松进行单元测试。

这就是我要做的事情。

答案 1 :(得分:0)

您可以测试匿名控制器。不必将控制器标识符传递给$controller(...)函数,而是必须传递控制器构造函数数组。

要执行此操作,您需要使控制器代码可供单元测试代码访问。这通常使用JavaScript的模块化工具(例如Webpack)来完成。但它可以在您的测试配置和<script></script>标签排序中完成。我建议使用工具。

无论如何,你最终得到三个文件:

// delete-item-controller.js

DeleteItemController = ['$scope', '$modalInstance', 'someService', 
  function($scope, $modalInstance, someService) {
    ....
  }
];
// state-controller.js

$scope.deleteSomething = function() {
    $modal.open(
        templateUrl: '/delete-item-modal.html',
        controller: DeleteItemController,
        resolve: {
          ...
        }
    });  
};
// delete-item-controller.spec.js

beforeEach(inject(function($controller) {
    $controller(DeleteItemController, {/*dependancies to be injected*/});
}));

替代示例,使用模块加载程序

使用Webpack看起来会有点不同......但它消除了DeleteItemController上隐藏的肮脏,隐含的全局对象。

// delete-item-controller.js

module.exports = ['$scope', '$modalInstance', 'someService', 
  function($scope, $modalInstance, someService) {
    ....
  }
];
// state-controller.js

var DeleteItemController = require("./delete-item-controller");

$scope.deleteSomething = function() {
    $modal.open(
        templateUrl: '/delete-item-modal.html',
        controller: DeleteItemController,
        resolve: {
          ...
        }
    });  
};
// delete-item-controller.spec.js

var DeleteItemController = require("./delete-item-controller");

beforeEach(inject(function($controller) {
    $controller(DeleteItemController, {/*dependancies to be injected*/});
}));
相关问题