How do I add svg files via MatIconRegistry in unit tests?

前端 未结 6 2039
不思量自难忘°
不思量自难忘° 2021-02-05 10:16

I\'m currently implementing \'unit testing\' in my angular application. However, if I run them, I receive multiple warnings/errors similar to this one: \'Error retrieving

相关标签:
6条回答
  • 2021-02-05 10:46

    can just do:

    ...
    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();
      }));
    
    ...
    
    });
    

    This will generate a test icon rendering without the http request

    0 讨论(0)
  • 2021-02-05 10:47

    What you could do is install ng-mocks and use MockModule to mock the MatIconModule in your tests e.g.:

    beforeEach(async(() => {
      TestBed.configureTestingModule({
        imports: [MockModule(MatIconModule)],
      }).compileComponents();
    }));
    
    0 讨论(0)
  • 2021-02-05 10:47

    There's also another way how to avoid this problem. Spectator (which is btw really awesome tool for Angular unit testing) has handy shallow flag, which basically prevents all child components (including mat-icon) to be compiled but handled as simple HTML tag instead.

    const createComponent = createComponentFactory({
      component: MyComponent,
      imports: [
        ...
      ],
      mocks: [
        ...
      ],
      providers: [
        ...
      ],
      shallow: true // <-- ignore child components
    });
    

    With this flag enabled, you don't need to import MatIconModule anymore, also you reduce the test runtime, because Angular doesn't compile extra components while running the test. This allows you to really focus on the component itself while writing unit tests, without worrying about the stuff you don't need anyway.

    It's a win-win if you ask me :)

    0 讨论(0)
  • 2021-02-05 10:51

    Mock the mat-icon selector with the following component at the top of the unit test

    @Component({
        selector: 'mat-icon',
        template: '<span></span>'
    })
    class MockMatIconComponent {
        @Input() svgIcon: any;
        @Input() fontSet: any;
        @Input() fontIcon: any;
    }
    

    Then override the MatIconModule in the unit test as follows

    beforeEach(() => {
        TestBed.configureTestingModule({
            declarations: [ ...],
            providers: [ ...  ],
            imports: [ MatIconModule, NoopAnimationsModule ]
        })
        .overrideModule(MatIconModule, {
        remove: {
           declarations: [MatIcon],
           exports: [MatIcon]
        },
        add: {
            declarations: [MockMatIconComponent],
            exports: [MockMatIconComponent]
       }
       })
      .compileComponents();
    

    You will no longer have the 'Error retrieving icon: Unable to find icon with the name ":myIcon"' issue when running the unit tests

    0 讨论(0)
  • Just spent a couple hours on this. It looks like Angular now provides a FakeMatIconRegistry. It squashed about 90% of the karma warnings, but still a few remain...

    Had to do a lot of this:

    TestBed.configureTestingModule({
        declarations: [ MyComponent ],
        imports: [
            ...
            MatIconModule,
        ],
        providers: [
            ...
            { provide: MatIconRegistry, useClass: FakeMatIconRegistry }
        ]
    }).compileComponents();
    
    0 讨论(0)
  • 2021-02-05 11:01

    Using typemoq for mocking; following worked for me:

    const mockIconRegistry = Mock.ofType<MatIconRegistry>();
    mockIconRegistry.setup(s => s.getNamedSvgIcon(It.isAny(), It.isAny())).returns(() => of(Mock.ofType<SVGElement>().object));
    

    and then

    providers: [{ provide: MatIconRegistry, useFactory: () => mockIconRegistry.object }]
    
    0 讨论(0)
提交回复
热议问题