我的测试在angular-mock 1.5.0上工作正常,但在1.5.1下,所有测试失败,原因是:
TypeError: undefined is not a constructor (evaluating 'angular.element.cleanData(cleanUpNodes)') in ../node_modules/angular-mocks/angular-mocks.js (line 2776)
$$cleanup@../node_modules/angular-mocks/angular-mocks.js:2776:32
$$afterEach@../node_modules/angular-mocks/angular-mocks.js:2746:23
这很奇怪,因为在那段代码中没有调用构造函数。 也许您可以提供更多信息? 测试失败的副本,最好是我们可以运行的测试。
在这里,您可以找到一个测试,它什么也没做,但是我们进行的每个测试都会失败(仅适用于1.5.1版,可以使用1.5.0)。
Test Runner Karma,测试框架Jasmine。 项目设置“应用程序基础”
https://github.com/HamburgOOU/hoou-webapp/blob/master/test/controllerTest/AboutControllerTest.js
看来您正在使用ui-router,对吗?
您能否尝试创建在此处运行的测试: http ://plnkr.co/edit/tpl:vojSWqpk1yBjQbbPeXRH?
作为建议,您还应该尝试从测试中删除依赖项,并查看究竟是什么引发了错误(应用程序模块中有很多依赖项)
是的,使用angular-ui-router(0.2.18)。
Trommorow我将尝试查找导致它的依赖项。
+1,我在尝试测试提供程序时收到一个非常类似的错误。
TypeError:“未定义”不是函数(评估“ angular.element.cleanData(cleanUpNodes)”)
在../node_modules/angular-mocks/angular-mocks.js:2776
在../node_modules/angular-mocks/angular-mocks.js:2746
编辑:1.5.1版发生此错误,我切换回1.5.0,一切正常。
在这里看到这个: https :
@petebacondarwin undefined is not a constructor
是PhantomJS在尝试调用未定义函数时产生的隐式错误。 等同于Chrome的a.something is not a function
错误。
我们在Angular / Mock 1.5.1上遇到了类似的错误,这在1.5.0上不是问题:
# PhantomJS
TypeError: undefined is not a constructor (evaluating 'angular.element('<div ng-app></div>').data('$injector', $injector)')
in /bower_components/angular-mocks/angular-mocks.js (line 2102)
/bower_components/angular-mocks/angular-mocks.js:2102:69
invoke@/bower_components/angular/angular.js:4443:22
/bower_components/angular/angular.js:4261:43
getService@/bower_components/angular/angular.js:4402:46
invoke@/bower_components/angular/angular.js:4434:23
/bower_components/angular/angular.js:4261:43
getService@/bower_components/angular/angular.js:4402:46
invoke@/bower_components/angular/angular.js:4434:23
/bower_components/angular/angular.js:4261:43
getService@/bower_components/angular/angular.js:4402:46
invoke@/bower_components/angular/angular.js:4434:23
/bower_components/angular/angular.js:4265:85
forEach@/bower_components/angular/angular.js:336:24
createInjector@/bower_components/angular/angular.js:4265:10
workFn@/bower_components/angular-mocks/angular-mocks.js:2922:60
# Chrome
TypeError: angular.element(...).data is not a function
at $get (/bower_components/angular-mocks/angular-mocks.js:2102:65)
at Object.invoke (/bower_components/angular/angular.js:4443:17)
at /bower_components/angular/angular.js:4261:37
at getService (/bower_components/angular/angular.js:4402:39)
at Object.invoke (/bower_components/angular/angular.js:4434:13)
at /bower_components/angular/angular.js:4261:37
at getService (/bower_components/angular/angular.js:4402:39)
at Object.invoke (/bower_components/angular/angular.js:4434:13)
at /bower_components/angular/angular.js:4261:37
at getService (/bower_components/angular/angular.js:4402:39)
请注意,我们将jQuery与Angular一起使用。
这可能与https://github.com/angular/angular.js/commit/75373dd4bdae6c6035272942c69444c386f824cd相关
@nikrolls
angular.element(...)。data不是函数
我是否正确理解angular.element(...)
(如果在Angular之前加载jQuery,别名为jQuery(...)
)会返回没有data
方法的东西? 好像很奇怪您可以在Chrome DevTools中启用“拒绝拒收”功能,然后在碰到此行时,检查究竟是什么返回以下表达式:
angular.element
angular.element(...)
(用您实际拥有的内容代替圆点)...
(用angular.element
的点代替圆点)谢谢!
自从角度v1.5.1起,我们有一个类似的问题。
should update data with success with redirect
PhantomJS 2.1.1 (Linux 0.0.0)
TypeError: undefined is not an object (evaluating '$location.path(interpolate(nextRoute.redirectTo, nextRoute.params)).search') in /project/app/bower_components/angular-route/angular-route.js (line 601)
commitRoute@/project/app/bower_components/angular-route/angular-route.js:601:82
$broadcast@/project/app/bower_components/angular/angular.js:17207:33
afterLocationChange@/project/app/bower_components/angular/angular.js:13127:28
/project/app/bower_components/angular/angular.js:13113:32
$eval@/project/app/bower_components/angular/angular.js:16884:28
$digest@/project/app/bower_components/angular/angular.js:16700:36
flush@/project/app/bower_components/angular-mocks/angular-mocks.js:1779:45
/project/app/modules/main/partners/partners.spec.js:338:31
invoke@/project/app/bower_components/angular/angular.js:4625:24
workFn@/project/app/bower_components/angular-mocks/angular-mocks.js:2933:26
Error: [$rootScope:inprog] $digest already in progress
http://errors.angularjs.org/1.5.1/$rootScope/inprog?p0=%24digest (line 17242)
beginPhase@/project/app/bower_components/angular/angular.js:17242:88
$digest@/project/app/bower_components/angular/angular.js:16680:19
flush@/project/app/bower_components/angular-mocks/angular-mocks.js:1779:45
/project/app/modules/main/partners/partners.spec.js:385:39
invoke@/project/app/bower_components/angular/angular.js:4625:24
workFn@/project/app/bower_components/angular-mocks/angular-mocks.js:2933:26
inject@/project/app/bower_components/angular-mocks/angular-mocks.js:2902:46
/project/app/modules/main/partners/partners.spec.js:381:23
undefined
在这种情况下,当测试包含inject()
函数时,总是会引发错误。 我猜spyOn($location, 'path');
的beforeEach
功能可能是问题。
describe('ctrl test', function () {
beforeEach(inject(function ($controller, $location) {
spyOn($location, 'path');
}));
describe('save()', function () {
it('should work', function(){
inject(function ($location) {
// some test code
});
});
});
});
@ 4kochi-您的问题实际上是您监视了一个函数,但未提供该间谍程序的实现。 换句话说,调用spyOn($location, path);
会使用间谍函数覆盖$location.path
方法,但该间谍函数会返回undefined
。 稍后,路由器尝试访问$location.path().search
,实际上是说undefined.search
。
您需要为间谍提供一个实现:伪造或传递:
spyOn($location, 'path').andCallThrough();
spyOn($location, 'path').andCallFake(function(url) { return {...}; });
感谢@petebacondarwin的提示,我有一个类似的想法。 但是我想知道为什么Angular 1.5.0可以使用完全相同的测试代码? 我错过了什么?
我在使用inject
时遇到同样的问题,例如
beforeEach(inject(function($rootScope) {
}));
@ dagda1 ,您能否提供https://github.com/angular/angular.js/issues/14251#issuecomment -198276079中提到的信息(以及错误的确切堆栈跟踪信息)?
在尝试升级到v1.5.2之后,我在测试中也看到了这个问题。 将angular-mocks.js的第2776行更改为:
angular.element.cleanData(cleanUpNodes);
至:
if (angular.element.cleanData) angular.element.cleanData(cleanUpNodes);
解决此问题。 在我们的例子中,出于各种原因,我们试图监视angular.element。
在我们的例子中,出于各种原因,我们试图监视angular.element。
那解释了错误。
angular.element
是一个非常基本的“功能”,在很大程度上依赖于内部。 我不建议将其存根。 (监视它并让事情通过应该是可以的)。
顺便说一句,将代码更改为if (angular.element.cleanData) angular.element.cleanData(cleanUpNodes);
会导致内存泄漏,这可能导致因果报应在庞大的测试套件上崩溃。
(是的,它已经发生了:笑脸:)
谢谢@gkalpak-不幸的是,任何形式的间谍(甚至只打来的间谍)似乎都会引起相同的问题。 作品中还有其他工作或其他建议可尝试吗?
@KeithPepin angular.element
是一个棘手的野兽。 您真的需要监视吗? 您可以举一个测试示例吗?
我有同样的问题。
得到一些错误味精:
PhantomJS 2.1.1 (Linux 0.0.0) 首页单元测试 首页内容控制器测试 调用获取数据接口 encountered a declaration exception FAILED
ReferenceError: Can't find variable: module in /client/modules/bootstrap/test/bootstrap.spec.js (line 4)
/client/modules/bootstrap/test/bootstrap.spec.js:4:23
global code@/client/modules/bootstrap/test/bootstrap.spec.js:3:9
PhantomJS 2.1.1 (Linux 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.041 secs / 0.001 secs)
我的测试如下:
describe( '首页模块单元测试', function(){
var $httpBackend,
$indexFactory;
beforeEach( module( 'Datatao.bootstrap' ) );
beforeEach( inject( function( _$httpBackend_, _IndexFactory_ ){
$httpBackend = _$httpBackend_;
$indexFactory = _IndexFactory_;
}) );
describe( '首页内容控制器测试', function(){
it( '调用获取数据接口', function(){
expect( true ).toBe( true );
});
});
});
我使用角度1.4.8和ui路由器0.2.15角度模拟1.5.2,但是将角度模拟降级到1.5.0之后,一切都很好。
如果您需要更多信息,请@me
@terminatorheart我们不支持使用不匹配的angular和angular-mock版本。 您是否尝试过同时使用1.5.2?
我试图在这里重新创建此问题https://github.com/petebacondarwin/issue-14251
但是karma start
对我来说很好。 您能否建议项目中要失败的其他内容?
从1.5.0移至1.5.1时,我也遇到类似的错误。
我们有以下代码在应用程序启动前做一些额外的工作。 现在,它失败并出现以下错误。
var injMods = ['ng','tcpInitModule','mpyInitModule'];
var initInjector = angular.injector(injMods);
var tcpMembershipSvc = initInjector.get('tcpMembershipSvc');
//使用tcpMembershipSvc提供程序进行一些工作
//最后启动
angular.bootstrap(document,['tcpMainModule']);
错误:
未捕获的错误:[$ jector:unpr ]未知提供程序:$ rootElementProvider <-$ rootElement <-$ location <-$ route <-$ location
http://errors.angularjs.org/1.5.1/ $ injector / unpr?p0 =%24rootElementProvider%…%24rootElement%20%3C-%20%24location%20%3C-%20%24route%20%3C- %20%24位置
在单元测试中,它失败并显示以下错误。
错误:[$$ jecter:modulerr ]由于以下原因,无法实例化模块ng:
TypeError:“未定义”不是对象(正在评估“ Function.prototype.bind.apply”)
在实例化时(c:/app/internal_packages/angular/angular.js:4640)
@mlakmal您可以为您的问题创建可运行的演示,以供我们测试吗?
@petebacondarwin我已经在下面添加了plnker。
https://plnkr.co/edit/J32cQo4Fo9fkiRH3pF3L?p=preview
我还注意到v1.5.0上也出现了单元测试错误...
@mlakmal我认为
单元测试问题似乎是由于未定义Function.prototype.bind
。 您正在使用PhantomJS 1.x吗?
您的其他问题确实与ngRoute
更改(5e37b2a)有关(实际上)是在暴露已经存在的问题。
最小复制为: angular.injector(['ng', 'ngRoute'])
另一个最小复制量(不涉及ngRoute
)将是: angular.injector(['ng']).get('$location');
问题是$location
服务取决于$rootElement
。 在启动应用程序之前,Angular不会提供$rootElement
(因为在此之前未知)。 尝试在引导应用程序的上下文之外实例化$location
,将使注入程序尝试获取$rootElement
并失败,因为此时没有$rootElement
提供程序。 。
TBH,我想不出从自定义注入器加载ngRoute
的理由( @mlakmal我很想知道有关您的用例的更多细节,即使只有OOC:smiley :)。
一个简单的解决方法是包括一个提供$rootElement
的虚拟额外模块:
angular.module('fakeRootElement', []).value('$rootElement', angular.element('<div></div>'));
var initInjector = angular.injector(['ng', 'InitModule', 'fakeRootElement']);
现在,在实际问题上, $location
使用$rootElement
拦截所有click
事件并以HTML5模式处理它们。 我们可以将其设为“可选”依赖项(例如,仅在定义了$rootElement
注入它,或者提供一个虚拟的$rootElement
并在引导过程中替换它)。
问题是我们应该吗?
嗨@gkalpak ,您是正确的,我们正在使用Phantom JS 1.9.8并尝试移至v2,但由于构建代理程序要求更改节点版本,因此在我们这方面的延迟(我们仍在v0.12.x上) 。 我在本地将PhantomJS升级到v2,并且单元测试看起来不错。 任何想法如何解决PhantomJS 1问题?
您的解决方法很好地解决了注射器上的问题。 我可以继续使用该修复程序,直到将来我们迁移到AngularJS 2(做梦了……)。
关于ngRoute的用例:我们有一些服务在这些CommonModule和InitModule上使用ngRoute的提供程序。 因此,在创建以支持单元测试执行时,我们必须为这些模块添加ngRoute作为模块依赖项。 我认为我们可以将其从那些依赖项中删除,仅在单元测试需要时才添加ngRoute。
在为karma conf添加以下polyfill之后,PhantomJS 1单元测试问题已解决。 不知道为什么在角度1.5.x升级后突然出现此错误...
@mlakmal是PhantomJS之前未出现此问题的原因,是Angular没有使用Function.prototype.bind
。 我们现在做,因为支持本机类是必需的,并且所有受支持的浏览器都提供了它。 (请注意,未明确支持PhantomJS,这意味着我们不对其进行测试,但是很多人使用它(包括ngMaterial项目直到不久前)都不会出现问题。)
关于依赖ngRoute
中的InitModule
:
ngRoute
仅提供一个提供程序( $routeProvider
),仅对注册路由有用。 我仍然不明白为什么需要创建包括它的自己的注入器(考虑到每个注入器将创建服务的不同实例-每个注入器的服务都是单例)。
如果您只是在加载InitModule
,以便可以保留一些帮助程序服务,那么将这些帮助程序服务提取到独立模块( InitModule
取决于)中可能是一个更好的主意。只能将该辅助模块加载到额外的进样器中。
@gkalpak我们在指令中使用了ngRoute的$ routeParams。 因此,这就是为什么我们将其添加到某些模块中的原因...但是我想我们可以将ngRoute模块分别添加到我们的spec文件中。
@mlakmal ,我的意思是我看不到在您手动创建的额外注射器(使用angular.injector([...])
)中需要ngRoute
的必要性,因为那将是一个单独的注射器(具有单独的服务)实例)。
大家好,抱歉,几天后再次提出,但是我刚刚遇到了这个问题。
我正在通过所有电话监视angular.element
,但是不幸的是,它仍然无法正常工作。
spyOn( angular, 'element' ).andCallThrough();
有什么想法吗?
@mattgrande我在想如果没有演示,我们将
对于Jasmine 2.x btw来说,这不是问题,因为它将spied函数的所有属性复制到间谍中(请参见demo )。
Jasmine 1.x仍然存在问题,Jasmine 1.x不会复制属性(请参见demo )。
您可以通过自己复制属性(全部或仅必要的属性,例如cleanData
)来解决此问题:
spyOn(angular, 'element').andCallThrough();
// Copy all properties
angular.extend(angular.element, angular.element.originalValue);
// or
// Copy `cleanData` only
angular.element.cleanData = angular.element.originalValue.cleanData;
TBH,我倾向于将其关闭为works as expected
/ won't fix
。 angular.element()
太基础了,如果有人监视它,他们最好为BC做准备(或使用Jasmine 2:stuck_out_tongue :)
在ngMock
内部解决此问题也很容易,例如,将angular.element.cleanData(...)
更改
var ngEl = angular.element;
(ngEl.cleanData || (ngEl.originalValue && ngEl.originalValue.cleanData) || angular.noop)(...)
但是明天可能会有另一个测试库崩溃。
因此,由于:
(a)这只是Jasmine 1.x(不是2.x)的问题,
(b)它只会破坏测试,而不会破坏应用程序代码,并且
(c)修复起来很容易,
我(仍然)倾向于不“解决”这个问题。
@gkalpak我倾向于同意你的看法。 这是“已知问题页面”的另一种情况,不是吗?
使用@KeithPepin解决方案,
如果(angular.element.cleanData)
angular.element.cleanData(cleanUpNodes);
为我工作
谢谢你们我将尝试更新到Jasmine 2.x(没有太多更改),但是如果事实证明这太麻烦了,我将使用Keith的解决方案。
更新:原来我已经在使用Jasmine 2.1,但是我已更新到最新版本,并且没有任何影响。
我最终使用了@gkalpak的“ extend”方法。 谢谢!
@mattgrande ,您将茉莉花升级到了哪个版本? 奇怪的是它没有用,因为它在我使用茉莉v2.4.1的演示中似乎可以正常工作:
角球1.5.2和1.5.3的相同错误
(茉莉花2.4.1)
茉莉花2.4.0; Angular版本1.5.2
嗨,我还有PhantomJS2,业力和茉莉花的未定义问题。 我正在使用最新版本的业力和茉莉花。 我的应用程序还使用ngRoute。
当我尝试注入$ rootScope和$ controller时,出现了我的问题。 我正在使用ngMock模拟我的模块之一。 作用域和控制器始终未定义。 但是,当我仅使用angular.module测试模块时,测试就会通过。 我没有使用spyOn。
关于可能是什么错误的任何建议?
从1.4.6升级到1.5.3时,我也遇到这个问题。
你们中的一个可以提供有关该问题的可运行演示吗?
@petebacondarwin这是travis失败的构建: https : //travis-ci.org/prestonvanloon/newrelic-angular/builds/118604417
编辑:这是导致它的PR https://github.com/prestonvanloon/newrelic-angular/pull/28
@prestonvanloon ,您的问题是您正在使用不同版本的angular和angular-mocks。
您应该始终使用匹配的版本。
@gkalpak谢谢!
@prestonvanloon :检查您使用的角度和角度模拟的版本。 我面临着同样的问题。 当我使用angular-mocks版本1.5.5和angular版本为1.4.7时,我遇到了相同的异常。 将我的角度版本升级到1.5.5时,没有出现任何错误,并且所有测试都成功运行。
谢谢@ varun85jobs和@gkalpak ,这正是我的问题
大家好,我有一个Ionic项目,其角度版本为1.5.3,角度为1.5.3,但是我仍然遇到相同的错误。 会是什么呢?
嗨,这里是同样的问题,我刚刚尝试了1.5.5和1.5.3,但仍然有问题,因为临时解决方案我们使用1.5.0。
KeithPepin的答案已为我解决,但我不希望更改库的代码
我们仍然没有适当的用例来监视angular.element
。 没有这个,我们将无法修复。
我们仍然需要一个实际运行的复制品,其中所使用的所有角度模块版本都匹配。
我遇到了这个问题:angular.element.parent不是一个函数
@ kristoff2016 ,这似乎不是一个相同的问题。 请打开一个新期刊,提供更多信息,例如相关代码,确切的错误消息,您的环境(浏览器,操作系统等)。 现场复制(使用CodePen,Plnkr等)也受到高度赞赏:
就我而言,问题是我使用的是旧版本的karma-phantomjs-launcher(^ 0.1.4而不是^ 1.0.0),它依赖于较旧的PhantomJS。 使用[email protected] ,它可以正常工作。
+1将karma-phantomjs-launcher和phantomjs升级到2+可以达到目的
到目前为止,对我而言唯一有效的选择是降级为角/角点1.5.0
自从首次报道以来已经有几个月了,这里仍然没有实际的复制品(带有匹配的版本)! 我们无法解决看不见的问题。 :担心:
我将关闭此窗口,但是如果我们得到复制,将很乐意重新打开。
@gkalpak ,您好,感谢您抽出evil:。 我已经保存在这个plnkr中。 因此,以下代码对您而言可能没有多大意义,但是我们针对特定情况解决了此问题:
var elSelect = angular.element;
angular.element = function(id) {
try {
return elSelect.call(angular, id);
} catch(err) {
return $(id);
}
};
因此,这在测试时适用于1.5.0
的angular和mocks,但不适用于1.5.1-1.5.7
。 我不知道这是否是这种情况,或者使用angular.element
其他情况是否也会中断。
谢谢@vitorarins。 如前所述,覆盖angular.element
这样的证书组件而不至少保留其属性是非常“顽皮的”事情。 使用上述angular.extend()
技术,您会很好。
var ngElement = angular.element;
angular.element = angular.extend(function(id) {
try {
return ngElement.call(angular, id);
} catch(err) {
return $(id);
}
}, ngElement);
非常感谢@gkalpak! 我希望至少这可以为其他有此问题的人提供参考。 再次感谢很多!
嗨,我也面临着同样的问题。 但是使用角度选择。 在我的控制器中,我正在像这样初始化select。
angular.element('select')。select2();
增加了如下的监视功能:
var ngElement = angular.element('select');
angular.element = angular.extend(function(id){
尝试 {
返回ngElement.call(angular,id);
} catch(err){
返回$(id);
}
},ngElement);
spyOn(ngElement,'select2')。and.callFake(function(){
});
PhantomJS 2.1.1(Mac OS X 0.0.0)错误
TypeError:尝试分配给只读属性。
在/node_modules/angular/angular.min.js:9
我已经完全阅读了这篇文章,并使用了angular 1.5.7和jasmine 2.4.1。 但是问题仍然没有解决。
@lathaMaramganti不是:
var ngElement = angular.element('select');
但:
var ngElement = angular.element;
您需要保存原始函数以扩展它,而不是对其进行调用。
最有用的评论
在尝试升级到v1.5.2之后,我在测试中也看到了这个问题。 将angular-mocks.js的第2776行更改为:
angular.element.cleanData(cleanUpNodes);
至:
if (angular.element.cleanData) angular.element.cleanData(cleanUpNodes);
解决此问题。 在我们的例子中,出于各种原因,我们试图监视angular.element。