繁体   English   中英

如何在单元测试中通过 MatIconRegistry 添加 svg 文件?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM