在单元测试期间,AngularJS 控制器中的 Leaflet 插件不可用
Leaflet plugin not available in AngularJS controller during unit tests
我正在使用 Karma + Mocha 来测试 Angular 中的控制器。下面的代码是控制器和测试规范的简化示例。 L.Control.Locate
是 LeafletJS plugin.
问题
在测试期间 运行 L.Control.Locate
应该在控制器被实例化时存在,但它不存在。它抛出:TypeError: L.Control.Locate is not a constructor
.
该应用程序在浏览器中按预期运行。
PhantomJS 和 Chrome 都出现错误。
在测试中,我用调试器确认 before 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 开发人员来说可能是显而易见的,但我忽略了它。
要模拟您的库对象,您需要
beforeEach(
function() {
window.L = {
Control: {
Locate: function() {
self = this;
//populate based on the API you're mocking
self.someMethod = angular.noop;
self.someProp = 'foo';
}
}
}
}
}
然后您想监视这些方法以确保您的控制器按预期调用它们,或者读取属性以确保您的控制器按预期设置它们。
请注意,我继承了将自身附加到 window 对象的代码(yuk!)。我尽可能地隐藏这种依赖性。我永远不会让控制器直接触摸它。
我正在使用 Karma + Mocha 来测试 Angular 中的控制器。下面的代码是控制器和测试规范的简化示例。 L.Control.Locate
是 LeafletJS plugin.
问题
在测试期间 运行 L.Control.Locate
应该在控制器被实例化时存在,但它不存在。它抛出:TypeError: L.Control.Locate is not a constructor
.
该应用程序在浏览器中按预期运行。
PhantomJS 和 Chrome 都出现错误。
在测试中,我用调试器确认 before 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 开发人员来说可能是显而易见的,但我忽略了它。
要模拟您的库对象,您需要
beforeEach( function() { window.L = { Control: { Locate: function() { self = this; //populate based on the API you're mocking self.someMethod = angular.noop; self.someProp = 'foo'; } } } } }
然后您想监视这些方法以确保您的控制器按预期调用它们,或者读取属性以确保您的控制器按预期设置它们。
请注意,我继承了将自身附加到 window 对象的代码(yuk!)。我尽可能地隐藏这种依赖性。我永远不会让控制器直接触摸它。