测试模态控制器:未知提供程序:$ modalInstanceProvider< - $ modalInstance,TypeError:尝试分配给只读属性

时间:2014-02-10 08:44:14

标签: javascript angularjs angular-ui-bootstrap angularjs-service

我对AngularJs有点新鲜。我正在使用Angular UI bootstrap(0.10.0)进行模态实现。我在测试模态控制器时遇到以下错误 使用AngularJs 1.2.7:TypeError:尝试分配给只读属性
使用AngularJs 1.2.12:未知提供者:$ modalInstanceProvider< - $ modalInstance。

我经历了很多类似的问题,但无法理解问题是什么。

  

正如Mahery的评论所指出的那样,$ modalInstance可通过AngularUI Bootstrap实现在控制器中注入。因此,我们不需要任何努力来“解决”或以某种方式使其可用。   Modal Window Issue (Unknown Provider: ModalInstanceProvider)



这是我的主控制器,导致在点击部分页面上的open时创建模态实例。

var SomeCtrl = function($scope, $modal){
$scope.open = function(){
    $scope.modalInstance = $modal.open({
      templateUrl: '/templates/simpleModal.html',
      controller: 'simpleModalController',
    });    

    $scope.modalInstance.result.then(
    function(){
        console.log("clicked OK");
    },
    function(){
        console.log("clicked Cancel");
    });
};

};

someCtrl.$inject = ["$scope", "$modal"];
angular.module('angularApp').controller("someCtrl", SomeCtrl);



这是模态控制器我希望测试它是否包含必要的功能(我打算稍后添加)

(function(){
   var SimpleModalController = function($scope, $modalInstance){

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

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

};

   SimpleModalController.$inject = ["$scope", "$modalInstance"];
   angular.module('angularApp').controller("simpleModalController", SimpleModalController);

})();



这是我为模态控制器编写的测试

describe('Testing simpleModalController',function() {
    var ctrlScope;
    var modalInstance;
    var ctrl;
    beforeEach(function() {
          module('angularApp');
          inject(function($rootScope, $modalInstance, $controller) {
          ctrlScope = $rootScope.new();
          modalInstance = $modalInstance;
          ctrl = $controller('simpleModalController', 
                 { 
                   $scope : ctrlScope, 
                   $modalInstance : modalInstance
              });
          });
    });

    it('should check existence of scope variables and functions when created', function() {
        console.log('pending test');
    });
});

我在app中的模态功能,测试主控制器和模态集成方面没有任何麻烦。但我无法测试模态控制器。我认为问题是在测试(简单模态控制器)中注入$ modalInstance。但正如前面提到的,angular-ui bootstrap使它可用。

感谢任何帮助。感谢。

5 个答案:

答案 0 :(得分:1)

拥有下一个模态控制器定义:

Intent intent = new Intent(this, HomeActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("Exit", true);
startActivity(intent);
finish();

您可以使用jasmine使用所需方法创建间谍对象,并在创建实例时将该对象传递给控制器​​:

OnCreate()

稍后在测试场景中,您可以检查间谍对象:

if( getIntent().getBooleanExtra("Exit", false)){
    finish();
}

答案 1 :(得分:0)

我也一直在与这个问题作斗争。问题是你试图在测试中实例化的控制器是一个完全不同的实例,$ modal服务实例化在内部传递实际模态窗口为$ modalInstance。请参阅示例http://angular-ui.github.io/bootstrap/#/modal中的js代码注释:

// Please note that $modalInstance represents a modal window (instance) dependency.
// It is not the same as the $modal service used above.

那么你如何测试你的控制器呢?我还没有找到解决方案,对不起。由于$ modal服务根据$ rootScope或您传入选项的范围创建新范围,因此难以实现您无法访问控制器范围。所以你松开了轨道。

您可以做的最少的事情是测试传递给结果承诺的函数。这是通过监视$ modal.open函数并返回一个mock来完成的。这里显示https://stackoverflow.com/a/21370703/2202143。并使用量角器等工具补充集成测试。

答案 2 :(得分:0)

所以..这是测试它的一种方式..

describe('Testing',function() {
   it('test',function() {
     inject(function($rootScope, $modal) {  
          var fakeModal = { };
          //Basically, what you want is for your modal's controller to get
          //initalized and then returned to you, so the methods in it can be unit tested

          spyOn(modal, 'open').andReturn(fakeModal);

          ctrl = $controller('Controller',
            {
                $scope : ctrlScope,             
                $modal: modal
             }); 
     });
   });
});

答案 3 :(得分:0)

查看问题所选答案的正确答案:Unit testing a modalInstance controller with Karma / Jasmine

我在同一个问题上挣扎了一段时间,这个问题(和答案)帮助我以一种非常干净的方式测试我的模态(以及打开/关闭它们的功能)!

答案 4 :(得分:0)

我不喜欢这里给出的任何答案所以我正在添加自己的答案。

我之所以不喜欢上述答案的原因是,一旦项目变得更大,他们就不会坚持。

对我来说,解决方案是简单地实现名为$ modalInstance ...

的角度服务

所以在spec下,我创建了一个名为shims的文件夹,我将其用于这些小项目。 (确保将其添加到karma.conf

我在那里实施

angular.module(..).service('$modalInstance', function(){
     this.dismiss = jasmine.createSpy('$modalInstance.dismiss'); 
     ... 
});

我发现这种方法更清洁,更易于维护和简单。

有时,我喜欢确保我的垫片仅为特定测试加载,在这种情况下,我只是给它一个特定的模块名称然后我必须为它添加module调用,否则它会赢得'加载。

我也强烈建议使用不同的库作为模态,我推荐使用ng-dialog有很多原因,但在这种情况下,我可以说它更适合测试,现在已经使用了一段时间了。