Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 测试AngularUI引导模式实例控制器_Javascript_Angularjs_Unit Testing_Angular Ui - Fatal编程技术网

Javascript 测试AngularUI引导模式实例控制器

Javascript 测试AngularUI引导模式实例控制器,javascript,angularjs,unit-testing,angular-ui,Javascript,Angularjs,Unit Testing,Angular Ui,这是这个问题的后续问题: 参考SO是一个很好的问题,答案非常有用。然而,在这之后我剩下的问题是:如何对模态实例控制器进行单元测试?在引用的SO中,测试调用控制器,但模拟模态实例控制器。可以说,后者也应该进行测试,但事实证明这是非常棘手的。原因如下: 我将从引用的示例中复制相同的示例,因此: .controller('ModalInstanceCtrl', function($scope, $modalInstance, items){ $scope.items = items; $sco

这是这个问题的后续问题:

参考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
  });
});
beforeach(注入(函数($rootScope,$modal){
scope=$rootScope.$new();
modalInstance=$modal.open({
模板:“”,
控制器:“ModalInstanceCtrl”,
范围:范围
});
});
(请注意,模板不能为空字符串,否则将以加密方式失败。)

现在的问题是,我对范围没有可见性,这是单元测试资源收集等的惯常方式。在我的实际代码中,控制器调用资源服务来填充一个选项列表;我尝试测试它时设置了一个expectGet以满足我的控制器正在使用的服务,我想验证控制器正在将结果放入其作用域。但是模态正在为模态实例控制器创建一个新的作用域(使用我传入的作用域作为原型),我不知道如何获得该作用域的一个洞。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
  });
}));
关于测试这个的“正确”方法有什么建议吗


(注意:为模态实例控制器创建派生作用域的行为并非意外–它是有文档记录的行为。我关于如何测试它的问题仍然有效。)

我通过直接实例化控制器来测试模态对话框中使用的控制器(与您最初认为的方法相同)

由于没有模拟版本的
$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
  });
}));
现在控制器的依赖关系已经满足,您可以像测试任何其他控制器一样测试该控制器

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')
,然后断言我的控制器正在适当的时间关闭对话框。

或者,如果您使用的是jasmine,您可以使用
createSpy
方法模拟
$uibModalInstance

beforeEach(inject(function ($controller, $rootScope) {
  $scope = $rootScope.$new();
  $uibModalInstance = jasmine.createSpyObj('$uibModalInstance', ['close', 'dismiss']);

  ModalCtrl = $controller('ModalCtrl', {
    $scope: $scope,
    $uibModalInstance: $uibModalInstance,
  });
}));
在不必对每个方法调用
spyOn
的情况下对其进行测试,假设您有两个作用域方法,
cancel()
confirm()


$uidModalInstance也存在同样的问题,您可以用类似的方法解决它:

var uidModalInstance = { close: function() {}, dismiss: function() {} };

$ctrl = $controller('ModalInstanceCtrl', {
   $scope: $scope,
   $uibModalInstance: uidModalInstance
});
或者,正如@yvemancera所说,您可以使用jasmine.createSpy方法,例如:

var uidModalInstance = jasmine.createSpyObj('$uibModalInstance', ['close', 'dismiss']);

$ctrl = $controller('ModalInstanceCtrl', {
   $scope: $scope,
   $uibModalInstance: uidModalInstance
});

遵循以下给定步骤:

  • 定义ModalInstance的存根,如下所示

            uibModalInstanceStub = {
                close: sinon.stub(),
                dismiss: sinon.stub()
            };
    
  • 在创建控制器时传递模态实例存根

        function createController() {
            return $controller(
                ppcConfirmGapModalComponentFullName,
                {
                    $scope: scopeStub,
                    $uibModalInstance: uibModalInstanceStub
                });
        }
    });
    
  • Stub方法close(),disclose()将作为测试的一部分被调用

    它('confirm modal-verify confirm action,on ok()调用调用modalInstance close()函数',函数(){ 动作=‘Ok’; scopeStub.item=测试项; createController(); scopeStub.ok(); }))


谢谢!我对Angular是个新手,我没有意识到你可以用你自己的值覆盖控制器DI。我得到了这个错误
参数'ModalInstanceCtrl'不是一个函数,没有定义。
…即使Sunil D的答案肯定有效,我觉得这绝对应该是大多数sinc实现的公认答案e你很可能会想监视他们。如果你不想这样,那么Sunil D的工作非常出色。还有一点。我同意,我发现自己用这种方式为模拟对象创建间谍,而不是我上面所做的。@perry谢谢你!但是这个问题没有被标记为jasmine,甚至没有被提及,所以Sunil的答案适用于任何测试框架,而我的答案适用于只有当你用的是茉莉花的时候。@yvesmancera这是真的。我想我错过了。所以当我看到角度测试的时候,我的大脑就进入了茉莉花:D@perryFWIW:我在选定的答案中使用了Sunil的方法,spyOn可以很好地使用它。