在单元测试期间,AngularJS控制器中没有Leaflet插件

时间:2016-03-31 21:01:51

标签: angularjs unit-testing leaflet mocha karma-mocha

我正在使用Karma + Mocha来测试Angular中的控制器。下面的代码是控制器和放大器的简化示例。测试规范L.Control.LocateLeafletJS plugin

问题

在测试运行期间,当实例化控制器时,L.Control.Locate应该存在,但事实并非如此。抛出:TypeError: L.Control.Locate is not a constructor

该应用在浏览器中按预期工作。

PhantomJS和Chrome都会出现错误。

在测试中,我已经通过调试器确认 MapCtrl2之前已实例化,L.Control.Locate已声明并附加到window.L.Control,应该是,但是在实例化控制器之前它就会丢失。

L的其他标准属性符合预期。

当我在控制器声明之前将L.Control.Locate.js粘贴到文件中时,错误消失。

我也尝试将$window注入控制器并查看$window.L.Control.Locate,但它仍未定义。

感谢您提供任何线索。

代码:

angular.module('app')
.controller('MapCtrl2', function ($scope) {

  // Throws error here.
  var locateControl = new L.Control.Locate();

  // Do something with locateControl.

});

describe('MapCtrl2', function () {

  var controller, scope;
  beforeEach(module('app'));
  beforeEach(inject(function ($controller, $rootScope) {
    scope = $rootScope.$new();
    controller = $controller('MapCtrl2', {
      $scope: scope
    });
  }));

  it('has L.Control.Locate', function() {
    expect(window.L.Control.Locate).to.be.an.instanceOf(Object)
  });

});

更新

关于全局使用L的问题,我意识到L可通过$window.L获得。虽然对于许多AngularJS开发者来说这可能是显而易见的,但我忽略了它。

1 个答案:

答案 0 :(得分:1)

要模拟您的库对象,您需要类似

的内容
beforeEach(
    function() {
        window.L = {
            Control: {
                Locate: function() {
                    self = this;
                    //populate based on the API you're mocking
                    self.someMethod = angular.noop;
                    self.someProp = 'foo';
                }
            }
        }
    }
}

然后你想监视方法以确保你的控制器按预期调用它们,或者读取属性,以确保你的控制器按预期设置它们。

注意我继承了将自身附加到窗口对象的代码(yuk!)。我尽可能地隐藏了这种依赖。我永远让控制器直接触摸它。