Angular,测试自定义提供程序和配置

Angular, testing custom provider and config

本文关键字:程序 配置 测试 自定义 Angular      更新时间:2023-09-26

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

提供商(根据需要而建)

  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中的函数,我认为我在那里没有访问权限?

或者我应该用另一种方式来处理这个问题?

我用的是因果报应、柴和西农。谢谢

颠簸!

编辑:

因此,我尝试通过将构造函数放入$get-like 中来对其进行测试

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

然而,在get中,this引用现在是关闭的(我们在this.$get中)。如果我可以公开构造函数,我可以调用它来向其中推送一个新的构造函数,并通过它进行测试。如果我试图在get的函数中记录一个this,那么this将引用整个get。

因此,在外部有一个this.module构造函数可以让我调用一个新的函数来决定它的操作方式。

编辑:凹凸!仍然无法解决这个问题:(

我在《如何测试AngularJS自定义提供程序》一文中找到了一个很好的答案,尤其是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(使用角度模拟函数)应该可以工作。