美文网首页react & vue & angular
Angular 单元测试实践 (1)

Angular 单元测试实践 (1)

作者: 品品下午茶 | 来源:发表于2022-06-02 08:02 被阅读0次

上一篇文章中,我们介绍了 Angular 单元测试的基础知识,本文开始介绍如何对 Angular 的主要元件进行单元测试。

测试组件

我们在使用 Angular CLI 创建项目时,会自动为 AppComponent 创建一个单元测试文件 app.component.spec.ts. 单元测试文件的名字以 .spec.ts 结尾,是一种约定,并且与被测试组件位于同一个路径中。

接下来,我们就对 app.component.spec.ts 进行研究,初步学习如何测试一个组件。 app.component.spec.ts 文件内容如下:

import { TestBed } from '@angular/core/testing’;
import { AppComponent } from './app.component’;

describe('AppComponent', () => {
  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [
        AppComponent
      ],
    }).compileComponents();
  });

  it('should create the app', () => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.componentInstance;
    expect(app).toBeTruthy();
  });

  it(`should have as title 'my-app-unittest'`, () => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.componentInstance;
    expect(app.title).toEqual('my-app-unittest’);
  });

  it('should render title', () => {
    const fixture = TestBed.createComponent(AppComponent);
    fixture.detectChanges();
    const compiled = fixture.nativeElement;
    expect(compiled.querySelector('.content span').textContent).toContain('my-app-unittest app is running!’);
  });
});

beforeEach

在文件的开头,是一个 beforeEach 初始化函数,完成测试前的准备工作。在 beforeEach 方法中,调用了 TestBed 类的 configureTestingModule 方法配置组件所在的模块。configureTestingModule 方法接收一个对象参数,而对象参数的值与模块的 @NgModule 装饰器的值相同。在这里,我们传入的是 declarations 数组,包含了 AppComponent 组件。完成模块配置后,调用 compileComponents 完成测试模块的构建。一旦构建成功,AppComponent 组件就属于该测试模块了。

createComponent

  it('should create the app', () => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.componentInstance;
    expect(app).toBeTruthy();
  });

在第一个单元测试用例中,使用 createComponent 方法创建了一个 AppComponent 组件装置类的对象。该对象是一个 ComponentFixture 类的实例,泛型的类型值是 AppComponent.

ComponentFixture 类专门用于组件的调试和测试,定义如下:

class ComponentFixture<T> {
  constructor(componentRef: ComponentRef<T>, ngZone: NgZone, _autoDetect: boolean)
  debugElement: DebugElement
  componentInstance: T
  nativeElement: any
  elementRef: ElementRef
  changeDetectorRef: ChangeDetectorRef
  componentRef: ComponentRef<T>
  ngZone: NgZone | null
  detectChanges(checkNoChanges: boolean = true): void
  checkNoChanges(): void
  autoDetectChanges(autoDetect: boolean = true)
  isStable(): boolean
  whenStable(): Promise<any>
  whenRenderingDone(): Promise<any>
  destroy(): void
}

在组件装置类的对象创建成功后,可以通过 componentInstance 属性,获得 AppComponent 组件类的实例。

最后,我们使用 toBeTruthy 匹配函数,验证 AppComponent 实例是否有效。

组件类属性

  it(`should have as title 'my-app-unittest'`, () => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.componentInstance;
    expect(app.title).toEqual('my-app-unittest’);
  });

在第二个单元测试用例中,对应用对标题属性的值进行了验证。因为我们已经获得了 AppComponent 实例,就可以对他的公共属性和方法进行测试。在单元测试用例中,我们使用 toEqual 方法验证 title 属性对值。

DOM 元素属性

it('should render title', () => {
    const fixture = TestBed.createComponent(AppComponent);
    fixture.detectChanges();
    const compiled = fixture.nativeElement;
    expect(compiled.querySelector('.content span').textContent).toContain('my-app-unittest app is running!’);
  });

在第三个单元测试用例中,对页面上渲染的文字进行了验证。因为组件不只包含类文件,还包含模板文件,所以也需要对类和模板对交互,或者说绑定关系,进行测试,才能保证测试更充分。

我们先调用了 ComponentFixture 类的 detectChanges 方法,目的是触发组件的变化检测机制,强制更新绑定的数据。然后,再使用组件的 nativeElement 属性,查找绑定数据的 DOM 元素,最后,验证 DOM 元素的 textContent 是否与绑定的数据相同。

运行单元测试

在项目所在的路径下,打开一个命令行,运行测试命令:

ng test

你会看到测试引擎开始执行单元测试用例,并打开一个浏览器,展示测试结果。

测试结果

相关文章

网友评论

    本文标题:Angular 单元测试实践 (1)

    本文链接:https://www.haomeiwen.com/subject/pzpzprtx.html