【问题标题】:Angular 2 Jasmine testing, Loading all components in app.component.ts?Angular 2 Jasmine 测试,加载 app.component.ts 中的所有组件?
【发布时间】:2017-12-02 08:12:29
【问题描述】:

我正在开发一个小型测试应用程序来更好地学习 Angular 2 和 Angular 2 中的单元测试。来自 react - Jest 背景;在 app.component.ts 中包含所有组件感觉很奇怪。

这就是我目前所拥有的组件层次结构的样子:

App.Component > Layout.Component > Header.Component > Nav.Component

当我运行 npm test 时,我得到了

的错误

main-header' 不是已知元素:

当我通过在 App.Component.spec.ts 中导入并声明绑定到该选择器的组件来解决此问题时,我会在下一个内联组件/选择器中得到相同的错误。

这是一个包含许多组件的大型应用程序吗?我可以看到 App.Component 的测试变得庞大且无法维护。经过几次谷歌搜索,产生了 AngularJS 和 Angular RC.X 结果。我已经走到了死胡同。我的直觉告诉我出了点问题,这不可能是在 Angular 2 中进行测试的方式......但我可能错了!

【问题讨论】:

标签: angular jasmine karma-jasmine angular-cli


【解决方案1】:

如果您有几个组件组合在一个模块中,您可以导入模块进行测试,而不是声明每个组件。

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

【讨论】:

    【解决方案2】:

    请详细说明您在 Angular 上生成项目的方式。我建议您使用 Angular CLI 来生成您的项目/组件/管道/服务,因为它会为您生成一个 spec.ts 文件,并将您的组件链接到一个模块。

    然后,将 Angular 的测试类视为一个空的测试平台,您必须在其中重新创建组件的结构才能进行测试。在实际的应用程序中,所有绑定都在模块内部进行,但在测试中,您必须导入和声明组件的所有组件才能使测试框架能够构建和测试它。

    在您展示的结构中,您将为每个组件创建一个测试类,例如:

    Nav.Component.spec.ts
    Header.Component.spec.ts
    Layout.Component.spec.ts
    App.Component.spec.ts
    

    在给定层次结构的情况下,您将在每一个上执行以下操作:

    Nav.Component.spec.ts

     import { NavComponent } from './your path to component';
     ...
     beforeEach(async(() => {
        TestBed.configureTestingModule({
          declarations: [ NavComponent  ]
        })
        .compileComponents();
     }));
    

    Header.Component.spec.ts

     import { NavComponent } from './your path to component';
     import { HeaderComponent } from './your path to component';
     ...
     beforeEach(async(() => {
        TestBed.configureTestingModule({
          declarations: [ NavComponent , HeaderComponent ]
        })
        .compileComponents();
     }));
    

    Layout.Component.spec.ts

     import { NavComponent } from './your path to component';
     import { HeaderComponent } from './your path to component';
     import { LayoutComponent } from './your path to component';
     ...
     beforeEach(async(() => {
        TestBed.configureTestingModule({
          declarations: [ NavComponent , HeaderComponent , LayoutComponent ]
        })
        .compileComponents();
     }));
    

    App.Component.spec.ts

     import { NavComponent } from './your path to component';
     import { HeaderComponent } from './your path to component';
     import { LayoutComponent } from './your path to component';
     import { AppComponent } from './your path to component';
     ...
     beforeEach(async(() => {
        TestBed.configureTestingModule({
          declarations: [ NavComponent , HeaderComponent , LayoutComponent, AppComponent  ]
        })
        .compileComponents();
     }));
    

    如果你这样做,应该可以工作。整个想法是在测试每个元素时使用它使用的所有元素来重构它以便工作。 如果有些地方不够清楚或不起作用,请提供更多详细信息。

    我给出的导入每个组件的示例是使其与您呈现的未链接到模块的组件结构一起工作的方法。但是,正如我告诉你的那样,这不是它的建造方式。 如果您使用 Angular CLI 生成,您可以执行以下操作: 生成您的模块,如:

    ng generate module layout -m app
    

    这将生成您的布局模块并将其导入 app.module 然后以相同的方式生成所有组件:

    ng generate component layout -m layout
    ng generate component header -m layout
    ng generate component nav -m layout
    

    这会生成所有组件,将每个组件导入到 layout.module 中,layout.module 已经导入到 app.module 中。 这样您就不必再导入任何内容,您的测试就可以正常工作了。

    这是每个元素之后的样子:

    app.module

    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    
    import { AppComponent } from './app.component';
    import { LayoutModule } from './layout/layout.module';
    
    @NgModule({
      declarations: [
        AppComponent
      ],
      imports: [
        BrowserModule,
        LayoutModule
      ],
      providers: [],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
    

    布局模块

    import { NgModule } from '@angular/core';
    import { CommonModule } from '@angular/common';
    import { LayoutComponent } from './layout.component';
    import { HeaderComponent } from '../header/header.component';
    import { NavComponent } from '../nav/nav.component';
    
    @NgModule({
      imports: [
        CommonModule
      ],
      declarations: [LayoutComponent, HeaderComponent, NavComponent]
    })
    export class LayoutModule { }
    

    布局组件

    import { Component, OnInit } from '@angular/core';
    
    @Component({
      selector: 'app-layout',
      templateUrl: './layout.component.html',
      styleUrls: ['./layout.component.css']
    })
    export class LayoutComponent implements OnInit {
    
      constructor() { }
    
      ngOnInit() {
      }
    
    }
    

    标题组件

    import { Component, OnInit } from '@angular/core';
    
    @Component({
      selector: 'app-header',
      templateUrl: './header.component.html',
      styleUrls: ['./header.component.css']
    })
    export class HeaderComponent implements OnInit {
    
      constructor() { }
    
      ngOnInit() {
      }
    
    }
    

    导航组件

    import { Component, OnInit } from '@angular/core';
    
    @Component({
      selector: 'app-nav',
      templateUrl: './nav.component.html',
      styleUrls: ['./nav.component.css']
    })
    export class NavComponent implements OnInit {
    
      constructor() { }
    
      ngOnInit() {
      }
    
    }
    

    【讨论】:

    • 我想你已经回答了这个问题。我目前正在使用 Angular-cli 来生成我的组件。看着您的 App.Component.Spec.ts,我的直觉是错误的,而我所做的是正确的。因此,如果您创建一个总共包含 80 个组件的应用程序,您应该将所有这些组件都包含到 App.Component.Spec.ts 文件中,对吗?
    • 您可以这样做,但这不是构建 Angular 应用程序的方式。为了模块化,Angular 提供了 NgModule 类来帮助我们将组件/服务/管道保持在我们用来构建应用程序的块中。在您的情况下,假设您声明了一个 LayerModule,您可以在其中导入 LayoutComponent、HeaderComponent 和 NavComponent。然后您只需将 LayerModule 导入您的 AppModule 而不是三个组件,spec.ts 类也是如此。
    • 这样,您的应用程序包含 80 个组件,它们将被分组到导入到其他模块的模块中,因此最终您只需要将几个模块导入到您的 app.module 中。跨度>
    • 但是根据我所看到的和您上面的示例,这不是它的工作方式。当你导入 LayerModule 时 app.spec 会要求你导入其中的三个组件。我可能误解了,你能提供一个LayerModule的例子吗?
    猜你喜欢
    • 1970-01-01
    • 2017-04-27
    • 1970-01-01
    • 2017-08-17
    • 1970-01-01
    • 2017-11-06
    • 2018-01-22
    • 2018-08-01
    • 1970-01-01
    相关资源
    最近更新 更多