![](/img/trans.png)
[英]How do I import and compile html files into the Jasmine unit tests using Angular 10?
[英]How do I add svg files via MatIconRegistry in unit tests?
我目前正在我的 angular 应用程序中实施“单元测试”。 但是,如果我运行它们,我会收到多个与此类似的警告/错误: 'Error retrieving icon: Unable to find icon with the name ":myIcon"'
。 我怀疑这可能是由于未将 svgs 添加到我的 MatIconRegistry 引起的。 我通常在我的 AppComponent 中这样做,如下所示:
constuctor(private iconRegistry: MatIconRegistry,
private sanitizer: DomSanitizer,
...) {
iconRegistry.addSvgIcon('myIcon', sanitizer.bypassSecurityTrustResourceUrl('./assets/icons/myIcon.svg'));
}
如果我运行另一个组件的单元测试,这将不会执行,因此不会将我的 svg 添加到注册表中。 我已经尝试将它添加到相应组件的 .spec 文件中,如下所示:
fdescribe('MyComponent', () => {
let component: MyComponent;
let fixture: ComponentFixture<MyComponent>;
let iconRegistry;
let sanitizer;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
...
],
imports: [
...
],
providers: [
...
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
.compileComponents();
}));
beforeEach(() => {
iconRegistry = TestBed.get(MatIconRegistry);
sanitizer = TestBed.get(DomSanitizer);
iconRegistry.addSvgIcon('myIcon', sanitizer.bypassSecurityTrustResourceUrl('./../../assets/icons/myIcon.svg'));
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create component', () => {
expect(component).toBeTruthy();
});
});
如果我运行它,它不起作用。 它只是返回不同的错误消息:
Error retrieving icon: <svg> tag not found
我最初的想法是我在路径上犯了一个错误,但在尝试了其他各种路径后,我确定情况并非如此。
有谁知道如何解决这个问题? 或者也许有更好的方法来做到这一点,因为我必须在我正在测试的每个组件中添加我的 svg 图标,这有点多余。
可以这样做:
...
import { MatIcon } from '@angular/material/icon';
import { MatIconTestingModule } from '@angular/material/icon/testing';
describe('MyComponent', () => {
...
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [MyComponent, MatIcon],
imports: [MatIconTestingModule],
}).compileComponents();
}));
...
});
这将生成一个没有 http 请求的测试图标渲染
在单元测试的顶部使用以下组件模拟mat-icon
选择器
@Component({
selector: 'mat-icon',
template: '<span></span>'
})
class MockMatIconComponent {
@Input() svgIcon: any;
@Input() fontSet: any;
@Input() fontIcon: any;
}
然后在单元测试中重写 MatIconModule 如下
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [ ...],
providers: [ ... ],
imports: [ MatIconModule, NoopAnimationsModule ]
})
.overrideModule(MatIconModule, {
remove: {
declarations: [MatIcon],
exports: [MatIcon]
},
add: {
declarations: [MockMatIconComponent],
exports: [MockMatIconComponent]
}
})
.compileComponents();
运行单元测试时,您将不再有'Error retrieving icon: Unable to find icon with the name ":myIcon"'
问题
刚刚花了几个小时在这上面。 看起来 Angular 现在提供了一个FakeMatIconRegistry
。 它压制了大约 90% 的 karma 警告,但仍有一些……
不得不做很多这样的事情:
TestBed.configureTestingModule({
declarations: [ MyComponent ],
imports: [
...
MatIconModule,
],
providers: [
...
{ provide: MatIconRegistry, useClass: FakeMatIconRegistry }
]
}).compileComponents();
使用 typemoq 进行模拟; 以下对我有用:
const mockIconRegistry = Mock.ofType<MatIconRegistry>();
mockIconRegistry.setup(s => s.getNamedSvgIcon(It.isAny(), It.isAny())).returns(() => of(Mock.ofType<SVGElement>().object));
进而
providers: [{ provide: MatIconRegistry, useFactory: () => mockIconRegistry.object }]
你可以做的是安装NG-嘲笑和使用MockModule嘲笑MatIconModule在测试中如:
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [MockModule(MatIconModule)],
}).compileComponents();
}));
还有另一种方法可以避免这个问题。 Spectator (顺便说一句,这是用于 Angular 单元测试的非常棒的工具)具有方便的浅标志,它基本上可以防止所有子组件(包括 mat-icon)被编译,而是作为简单的 HTML 标记处理。
const createComponent = createComponentFactory({
component: MyComponent,
imports: [
...
],
mocks: [
...
],
providers: [
...
],
shallow: true // <-- ignore child components
});
启用此标志后,您不再需要导入 MatIconModule ,也可以减少测试运行时间,因为 Angular 在运行测试时不会编译额外的组件。 这允许您在编写单元测试时真正专注于组件本身,而不必担心您不需要的东西。
如果你问我,这是双赢的:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.