在Angular中使用升级后的AngularJS组件,测试时遇[$injector:unpr]错误
解决AngularJS指令在Angular组件测试中注入失败的问题
嘿,我之前在Angular和AngularJS混合开发的测试里踩过一模一样的坑!这个[$injector:unpr]错误的核心原因是:你在Angular的TestBed环境里尝试直接注入AngularJS的指令,但Angular的测试注入器和AngularJS的$injector是完全独立的两个系统,根本找不到contactBoxDirective的provider。下面是具体的解决步骤:
1. 先搭好Angular与AngularJS的测试兼容桥梁
首先得确保测试模块里引入了UpgradeModule,这是混合开发测试的核心依赖,还要初始化AngularJS的注入器:
import { UpgradeModule } from '@angular/upgrade/static'; import { TestBed } from '@angular/core/testing'; import { personInfoComponent } from './person-info.component'; describe('personInfo Component', () => { let upgradeModule: UpgradeModule; beforeEach(async () => { await TestBed.configureTestingModule({ imports: [UpgradeModule], declarations: [personInfoComponent] }).compileComponents(); // 初始化AngularJS注入器,这里要替换成你自己的AngularJS模块名 upgradeModule = TestBed.inject(UpgradeModule); upgradeModule.bootstrap(document.body, ['yourAngularJSModuleName']); }); });
2. 别直接注入指令,通过模板渲染来测试
AngularJS指令是靠模板渲染生效的,不是像Angular服务那样注入使用的。所以你的测试应该聚焦在组件渲染后,指令是否正常渲染,而不是尝试注入contactBoxDirective:
it('should render contactBoxDirective properly', () => { const fixture = TestBed.createComponent(personInfoComponent); fixture.detectChanges(); // 先检查指令对应的DOM元素是否存在(这里假设指令的标签选择器是<contact-box>) const contactBoxElement = fixture.nativeElement.querySelector('contact-box'); expect(contactBoxElement).toBeTruthy(); // 如果要测试指令的内部逻辑,可以通过AngularJS的$injector获取它的控制器 const contactBoxDirectiveDefs = upgradeModule.$injector.get('contactBoxDirective'); // 注意:get返回的是数组,因为可能有多个同名指令(不同限制符,比如E/A/C),取第一个就行 const contactBoxCtrl = contactBoxDirectiveDefs[0].controller; // 这里可以对控制器的方法或属性做断言 });
3. 检查AngularJS模块的注册
一定要确认包含contactBoxDirective的AngularJS模块,已经在上面的bootstrap步骤里正确引入了,也就是yourAngularJSModuleName必须是你定义contactBoxDirective的那个模块名,不然测试时还是找不到指令。
4. 分清Angular和AngularJS的注入方式
最后再提醒一句,别搞混两者的注入逻辑:
- Angular的服务/组件用
TestBed.inject()获取 - AngularJS的服务/指令用
upgradeModule.$injector.get()获取,而且指令返回的是数组,要根据你的指令类型(元素/属性/类)取对应的项。
另外,也可以再检查下你的contactBoxDirective在AngularJS里的注册是否正确,比如是不是在对应的模块里用directive方法注册了:
// AngularJS模块中的指令注册示例 angular.module('yourAngularJSModuleName') .directive('contactBox', function() { return { restrict: 'E', // 假设你用的是元素指令 template: '<div class="contact-box">...</div>', controller: function() { // 控制器逻辑 } }; });
内容的提问来源于stack exchange,提问作者user1722043
相关产品推荐
相关产品推荐

