【问题标题】:How to unit test $uibModal in Jasmine? (unit testing injected library)如何在 Jasmine 中对 $uibModal 进行单元测试? (单元测试注入库)
【发布时间】:2019-08-02 03:03:13
【问题描述】:

所以我在 bootstrap 中使用 $uibModal,并且我的 AngularJS 控制器中有以下代码:

vm.openPopup = function() {
  $uibModal.open({
    templateUrl: 'popup.html',
    controller: function() {
       var modal = this;

       modal.hi = function() {
         // some code here
       }
    }
  });
};

我将如何在 Jasmine 中调用 modal.hi 函数并对其进行单元测试以确保其正常工作?

【问题讨论】:

    标签: angularjs unit-testing jasmine karma-jasmine angular-ui-bootstrap


    【解决方案1】:

    因此,测试此代码的主要问题是,您基本上在 另一个 匿名函数 ($uibModal.open) 中“埋藏”了一个匿名函数 (modal.hi)。这使得测试非常棘手。

    您有几个选择:a.) 您可以模拟 $uibModal 服务,b.) 您可以重构您的代码,或者 c.) 您可以将您的 hi 函数放到 vm本身,然后从您的测试中调用它。我认为最后一个选项是最方便的,但这里是所有三种方法的一些示例。

    选项 1:模拟 $uibModal 服务

    describe('Test vm.openPopup', function () {
      var mockUibModal = {
        open: function(options){
          var ctrl = options.controller();
          // call your `hi` function:
          ctrl.hi();
        }
      };
    
      beforeEach(function(){
        module(function($provide){
          $provide.value('$uibModal', mockUibModal);
        });
      });
    });
    

    然后,您可以调用 vm.openPopup 方法,然后开始测试结果。请注意,module 函数来自 angular-mocks,您需要在测试中安装/包含它。相关问题:“How do you mock a service in AngularJS when unit testing with jasmine?

    选项 2:重构代码

    这是我经常使用的一种模式,它涉及将您希望测试的逻辑/功能转移到一个单独的工厂:

    var app = angular.controller('YourController', function ($uibModal, MyHelperFactory) {
      var vm = this;
      var modal;
    
      var helper = MyHelperFactory(vm, modal);
    
      vm.openPopup = function () {
        $uibModal.open({
          templateUrl: 'popup.html',
          controller: function () {
            modal = this;
            modal.hi = helper.hi;
          }
        });
      };
    });
    
    app.factory('MyHelperFactory', function () {
      return function (vm, modal) {
        return {
          hi: function () {
            // some code here, maybe it needs to reference the `vm` object, whatever...
          }
        }
      };
    })
    

    这种方法的好处是您可以自行测试MyHelperFactory,无需实例化YourController,也无需涉及$uibModal 服务。这通常是我最喜欢的方法:没有内联/匿名函数 - 将该逻辑放入辅助工厂,并从我的控制器中取出。

    选项 3:将 hi 函数拖放到 vm

    var app = angular.controller('YourController', function ($uibModal, MyHelperFactory) {
      var vm = this;
    
      // this pattern allows your function to be scoped with the not-yet-existing `modal` object
      vm.hi = function (modal) {
        return function () {
          // some code here
        }
      };
    
      vm.openPopup = function () {
        $uibModal.open({
          templateUrl: 'popup.html',
          controller: function () {
            var modal = this;
            modal.hi = vm.hi(modal);
          }
        });
      };
    });
    

    然后,您可以通过在测试中调用vm.hi 来测试它。我称这种方法为“肮脏的”,因为它将hi 方法添加到vm 对象,并且我通常避免向vm 对象添加控制器范围实际上不需要的任何属性。但在这种情况下,我们违反了该规则,因为这是“公开”您希望测试的函数的最快/最简单的方法。

    【讨论】:

    • 我认为这会很困难。不过,所有这些都是不错的选择,谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-02-16
    • 2017-04-14
    • 2012-01-08
    • 2016-04-11
    • 1970-01-01
    • 2019-11-02
    • 1970-01-01
    相关资源
    最近更新 更多