【问题标题】:Testing components with Font Awesome Icons Module使用 Font Awesome 图标模块测试组件
【发布时间】:2019-03-24 21:39:20
【问题描述】:

我目前在一个 Angular 6 项目中工作,我已经使用 Fort-awesome 模块导入了几个新的 font-awesome 5 图标。

正如预期的那样,由于无法在我的页面中呈现 fa-icon 选择器,现在我的一些单元测试(Karma + Jasmine)将无法通过。

我知道我可以在 TestBed 中为每个组件使用 CUSTOM_ELEMENTS_SCHEMA,但我不知道这样做是否会产生其他副作用,使我的单元测试不太可靠(即其他子组件可能会停止测试)。

另一种选择是在每个所需的单元测试中简单地导入模块,并在每个单元测试中添加带有所需图标的 library.add()。但是,我确实认为这最终可能会很乏味,因为根据应用程序的类型可能会有 20 到 50 个图标。

我也想过,但还没有尝试过为图标添加一个存根模块,所以我只是“忽略”它们。我认为这可能是合理的,但不确定在这种情况下最佳做法是什么。

下面是我在 App.Module 中导入的摘录

import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
import { library } from '@fortawesome/fontawesome-svg-core';
import { faLock, faHourglassHalf, faLockOpen } from '@fortawesome/free-solid-svg-icons';

在构造函数中

export class AppModule {
  constructor() {
    library.add(
      faHourglassHalf, // Task in progress
      faLockOpen, // Archive task
      faLock
    );
  }
} 

完整的回购:https://github.com/Narshe1412/Code-Institute-Interactive-Frontend-Project/tree/taskman

据我所知,这不是辩论论坛,我只想问:

  • 在这个用例中使用 CUSTOM_ELEMENTS_SCHEMA 有什么副作用,如果使用它时存在可靠性问题,那么其他两个选项中的哪一个更可取?

【问题讨论】:

  • 鉴于您正在使用库,并且使用未添加到库中(或意外删除)的图标可能会使您的组件失败,我绝对不会使用 CUSTOM_ELEMENTS_SCHEMA。我只需在测试和 AppModule 中导入一个导入 FontAwesomeModule 的模块并将图标添加到库中。
  • 还要确保检查library documentation

标签: angular unit-testing karma-jasmine


【解决方案1】:

我不喜欢其他解决方案,即使它们可能有效。对我来说,在单元测试中导入 AppModule 似乎不干净。

我的解决方案是将图标与其他内容分开,如下所述。这个解决方案有点像已经接受的答案,但在我看来更干净:

import { NgModule } from '@angular/core';
import { FontAwesomeModule, FaIconLibrary } from '@fortawesome/angular-fontawesome';
import { faDownload, faUpload, faFileExport, faCircle, faChevronRight, faChevronDown, faPlus, faTimes } from '@fortawesome/free-solid-svg-icons';

@NgModule({
  imports: [ FontAwesomeModule ],
  exports: [ FontAwesomeModule ]
})
export class IconsModule {
  constructor(library: FaIconLibrary) {
    // add icons to the library for convenient access in other components
    library.addIcons(faDownload, faUpload, faFileExport, faCircle, faChevronRight, faChevronDown, faPlus, faTimes);
  }
}

然后在任何需要的地方导入 IconsModule,无论是在应用程序本身还是在测试中:

应用模块:

import { IconsModule } from './icons.module';

@NgModule({
  declarations: [...],
  imports: [
    ...
    IconsModule,
  ],
  bootstrap: [...]
})
export class AppModule {}

单元测试:

describe('MyComponent', () => {
  let component: MyComponent;
  let fixture: ComponentFixture<MyComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ MyComponent ],
      imports: [
        ...
        IconsModule,
      ]
    })
    .compileComponents();
  }));

  ...

});

HTML:

<fa-icon icon="download"></fa-icon>

很好的副作用:如果您曾经将字体库从 Font Awesome 更改为其他内容,现在这会容易得多,因为您只需更改 IconsModule 和图标的相应 HTML 代码。

【讨论】:

  • 这似乎是最干净、最模块化的方法,应该是公认的答案。
【解决方案2】:

您现在可以像这样使用 font-awesome 测试模块:

import {FontAwesomeTestingModule} from '@fortawesome/angular-fontawesome/testing';

TestBed.configureTestingModule({imports: [ FontAwesomeTestingModule ]}).compileComponents();

【讨论】:

    【解决方案3】:

    我只想放弃“第三个”选项。这是我和我的团队一直在使用和喜欢的方法。

    该模块引入了 FontAwesomeModule。

    import { NgModule } from '@angular/core';
    import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
    
    @NgModule({
      declarations: [
        AppComponent
      ],
      imports: [
        FontAwesomeModule
      ],
      exports: [
        FontAwesomeModule
      ]
    })
    
    export class AppModule { }
    

    实际使用字体 awesome 图标的组件只导入它需要知道的图标。

    import {
      Component
    } from '@angular/core';
    
    import { faLock } from '@fortawesome/free-solid-svg-icons';
    
    @Component({
      selector: 'app-fa-example',
      template: '<fa-icon [icon]="faLock"></fa-icon>'
    })
    export class AppComponent {
      faLock = faLock;
    }
    

    然后在我们的*.spec.ts 文件中,我们有如下设置:

    TestBed.configureTestingModule({
      imports: [
        AppModule
      ]
    })
    .compileComponents();
    

    由于FontAwesomeModule 是在AppModule 中导出的,因此可以通过AppModule 导入在此处的测试台上使用它。由于图标是在组件中显式导入的,因此无需在此处library.add(...) 指定模块/组件中使用的所有字体真棒图标。

    【讨论】:

    • 感谢您的意见。我将尝试这种方法,看看它是否适用于我的代码库的其余部分。事实上,它可能有助于开始对我在工作中一直忽略自动化测试的更大项目进行单元测试。
    【解决方案4】:

    看起来这个问题已经有一个公认的答案,但我会尝试补充来自相关主题的信息。

    您可以模拟来自外部模块的所有内容,但导入组件的选择器除外。正如您提到的,有一种简单的方法是禁用此类错误。

    Can't bind to 'icon' since it isn't a known property of 'fa-icon'

    import { NO_ERRORS_SCHEMA } from '@angular/core';
    
    ...
    
    TestBed.configureTestingModule({
      schemas: [ NO_ERRORS_SCHEMA ],
      ...
    

    NO_ERRORS_SCHEMA 告诉 Angular 编译器忽略无法识别的元素和属性。

    否则我建议将 FontAwesome 直接添加到测试平台中,尽管这是一项繁琐的任务。它提高了可读性并避免在测试模块中导入冗余组件。当您拥有多个组件时,这主要会成为一个问题。

    TestBed.configureTestingModule({
      imports: [
        FontAwesomeModule
      ]
    })
    .compileComponents();
    
    

    【讨论】:

    • 感谢您的意见。我也考虑过这一点,但我相信它会遇到与 CUSTOM_ELEMENTS_SCHEMA 相同的问题,即您覆盖了另一个您不想但忘记导入的组件。
    猜你喜欢
    • 1970-01-01
    • 2014-12-27
    • 2013-01-22
    • 2013-08-11
    • 1970-01-01
    • 2022-08-08
    • 2019-12-31
    • 1970-01-01
    • 2018-05-22
    相关资源
    最近更新 更多