【问题标题】:Angular, testing custom provider and configAngular,测试自定义提供程序和配置
【发布时间】:2015-03-18 14:31:14
【问题描述】:

我有一个提供程序,它使用构造函数获取其中设置的项目,然后返回一个带有一些函数的 $get 以供使用。问题是 $get 函数都使用我拥有的构造函数设置的对象,并且我希望能够设置构造函数以进行测试(或者可能是不同的方法?)。这是我所拥有的。

提供者(为 requirejs 构建)

  function URLprovider(angular, URLfactory, underscore) {
     var metadata = {
         componentName: 'URLprovider',
         moduleName: 'test.URLprovider'
     };

     $moduleObjectProvider.$inject = [];

     function $moduleObjectProvider() {

         var currentModules = {};

         function modulePush(currentModule, name) {
                 var tempMod = {};
                 tempMod[name] = currentModule;
                 _.extend(currentModules, tempMod);
             }

        //constructor
         this.moduleConstructor = function(name, cb) {
             if (!currentModules[name]) {
                 this.states = [];
                 this.callback = cb;
                 modulePush(this, name);
             }
         };

         this.$get = $get;

         $get.$inject = ['URLfactory', '$log', '$location'];

         function $get(URLfactory, $log, $location) {

             return {
                 go: function(name, stateName, options) {

                 },
                 prep: function(name, stateName, options) {

                 },
                 modules: function() {
                     return currentModules;
                 }
             };
         }
     }

     angular.module(metadata.moduleName, []).provider(metadata.componentName, $moduleObjectProvider);

所以 - 我要测试的函数在 $get.如果我在测试中使用 console.log URLprovider,我只会取回 get 中的函数。这些 get 函数中的每一个都使用使用构造函数设置的 currentModules 变量。因此,在正常情况下,我只需将其设置在配置中,例如 -

  .config(function(URLproviderProvider) {
                 var callback = function(name, obj) {
            console.log(name, obj);
        }

        var mod = new URLproviderProvider.moduleConstructor("module1,", callback)
            .addState("calender", ["day", "week", "month"]);


    })

这样就会将该对象推入 currentModules。我需要这样做以进行本质上的测试,因为如果没有 currentModules 中的某些内容,$get 中的所有函数都将无法正常运行。

所以我想知道的是 -

有没有办法在测试时伪造变量 currentModules?

有没有办法模拟配置来设置 currentModules(在 beforeEach 中)进行测试,我觉得我需要以不同的方式公开构造函数(我不确定现在如何)因为当我登录时测试中的 URLprovider,它只返回 $get 中的函数,我认为我无法访问它吗?

或者我应该以其他方式解决这个问题吗?

我正在使用 Karma、Chai 和 Sinon。谢谢!

撞!

编辑:

所以我尝试通过将构造函数放入 $get 中来将其暴露给测试 - 就像

     moduleConstructor: function(name, cb) {
         if (!currentModules[name]) {
             this.states = [];
             this.callback = cb;
             modulePush(this, name);
         }
     };

但是,在 get 内部,this 引用现在关闭了(我们在 this.$get 内部)。如果我可以公开构造函数,我可以调用它来将一个新的推入其中并通过它进行测试。如果我尝试在 get 中的函数内记录 this,则 this 引用整个 get。

因此,在外部有一个 this.moduleConstructor 函数可以让我调用一个新函数来了解我希望它如何工作。

编辑:撞!还是想不通这个:(

【问题讨论】:

    标签: javascript angularjs unit-testing


    【解决方案1】:

    我在How to test AngularJS custom provider 的帖子中找到了一个非常好的答案,尤其是来自 Stephane Catala(4 月 22 日)的答案,它提供了一个通用函数 providerGetter,让您可以访问 Jasmine 测试中的提供者。您还可以访问提供商提供的服务。使用该功能(在 Jasmine 中),您可以执行以下操作:

    describe("provider test", function() {
      var infoProvider, info;
    
      function providerGetter(moduleName, providerName) {
        var provider;
        module(moduleName, 
           [providerName, function(Provider) { provider = Provider; }]);
        return function() { inject(); return provider; }; 
      }
    
      beforeEach(function() {
        infoProvider = providerGetter('test', 'infoProvider')();
      });
    
      it('should return nothing if not set', function() {
        inject(function(_info_) { info = _info_; });
        expect(info.getInfo()).toEqual('nothing');
      });
    
      it('should return the info that was set', function() {
        infoProvider.setInfo('something');
        inject(function(_info_) { info = _info_; });
        expect(info.getInfo()).toEqual('something');
      });
    });
    

    这个测试的提供者很简单

        angular
            .module('test', [])
            .provider('info', info);
    
        function info() {
            var nfo = 'nothing';
            this.setInfo = function(s) { nfo = s; };
            this.$get = Info;
    
            function Info() {
                return { getInfo: function() {return nfo;} };
            }
        }
    

    不完全确定如何将其转换为 sinon,但 providerGetter(它使用 angular-mocks 函数)应该可以工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-08-02
      • 2013-01-24
      • 1970-01-01
      • 1970-01-01
      • 2019-01-29
      • 1970-01-01
      • 2019-03-05
      • 1970-01-01
      相关资源
      最近更新 更多