一尘不染

测试AngularUI Bootstrap模式实例控制器

angularjs

引用的SO是一个非常有用的问题,答案非常有用。但是,这之后我剩下的问题是:如何对模态实例控制器进行单元测试?在引用的SO中,测试了调用控制器,但模拟了模态实例控制器。可以说后者也应该进行测试,但是事实证明这非常棘手。原因如下:

我将在此处从引用的SO复制相同的示例:

.controller('ModalInstanceCtrl', function($scope, $modalInstance, items){
  $scope.items = items;
  $scope.selected = {
    item: $scope.items[0]
  };

  $scope.ok = function () {
    $modalInstance.close($scope.selected.item);
  };

  $scope.cancel = function () {
    $modalInstance.dismiss('cancel');
  };
});

因此,我首先想到的是,我将直接在测试中实例化该控制器,就像在测试中的其他任何控制器一样:

beforeEach(inject(function($rootScope) {
  scope = $rootScope.$new();
  ctrl = $controller('ModalInstanceCtrl', {$scope: scope});
});

这不起作用,因为在这种情况下,angular没有提供注入$modalInstance的提供程序,因为它是由UI模态提供的。

接下来,我转向计划B:使用$ modal.open实例化控制器。这将按预期运行:

beforeEach(inject(function($rootScope, $modal) {
  scope = $rootScope.$new();
  modalInstance = $modal.open({
    template: '<html></html>',
    controller: 'ModalInstanceCtrl',
    scope: scope
  });
});

(请注意,模板不能为空字符串,否则会因密码错误而失败。)

现在的问题是,我对范围没有任何了解,这是对单元测试资源收集进行惯用的方式,等等。在我的真实代码中,控制器调用资源服务来填充选择列表。我对此进行的测试尝试设置了一个ExpectGet来满足控制器使用的服务,并且我想验证控制器是否将结果放入其范围内。但是模态正在为模态实例控制器创建一个
新的 作用域(使用我作为原型传入的作用域),我无法弄清楚如何获得该作用域的漏洞。modalInstance对象没有进入控制器的窗口。

关于“正确”的测试方法有什么建议吗?

(注意:为模态实例控制器创建派生范围的行为并非意外-这已得到记录,这是我的问题,无论如何,它的测试仍然有效。)


阅读 209

收藏
2020-07-04

共1个答案

一尘不染

我通过直接实例化控制器来测试模式对话框中使用的控制器(与您最初在上面所做的相同)。

由于没有$modalInstance的模拟版本,我只需创建一个模拟对象并将其传递给控制器​​即可。

var modalInstance = { close: function() {}, dismiss: function() {} };
var items = []; // whatever...

beforeEach(inject(function($rootScope) {
  scope = $rootScope.$new();
  ctrl = $controller('ModalInstanceCtrl', {
      $scope: scope, 
      $modalInstance: modalInstance, 
      items: items
  });
}));

现在,控制器的依赖关系已满足,您可以像其他任何控制器一样测试该控制器。

例如,我可以这样做spyOn(modalInstance,'close'),然后断言我的控制器正在适当的时间关闭对话框。

2020-07-04