本文继续介绍如何对 Angular 的管道(pipe)、指令(directive)和表单(form)进行单元测试。
测试管道
Angular 的指令是一个实现了 PipeTransform
接口的 TypeScript 类,暴露了 transform
方法。指令操作通常是同步的,很少与 DOM 元素进行交互,也几乎没有什么依赖。因此,对指令的单元测试也比较简单,甚至不需要 Angular 的测试工具类。
考虑这样一个管道 CommaSeperatorPipe
:把逗号分割的字符串转换成一个列表:
import { Pipe, PipeTransform } from '@angular/core’;
@Pipe({
name: ‘commaSeperator’
})
export class CommaSeperatorPipe implements PipeTransform {
transform(value: string): string[] {
return value.split(',’);
}
}
测试代码只需要实例化一个管道对象,向 transform
方法传入一些模拟的数据,验证该方法转换的结果即可:
import { CommaSeperatorPipe } from './comma-seperator.pipe’;
describe('CommaSeperatorPipe', () => {
it('create an instance', () => {
const pipe = new CommaSeperatorPipe();
expect(pipe).toBeTruthy();
});
it('should return an array', () => {
const pipe = new CommaSeperatorPipe();
expect(pipe.transform('1,2,3,4,5')).toEqual(['1', '2', '3', '4', '5’]);
});
});
测试报表页面:
管道测试报表页面测试指令
指令通常用来改变一个元素、组件或另一个指令的行为。指令一般和组件一起协同工作,没有外部的依赖。
考虑这样一个指令 HighlightDirective
:基于绑定的数据值,设置元素的背景颜色:
import { Directive, ElementRef, Input, OnChanges } from '@angular/core’;
@Directive({ selector: '[highlight]’ })
/**
* 设置宿主元素的背景颜色
*/
export class HighlightDirective implements OnChanges {
defaultColor = 'rgb(211, 211, 211)'; // 默认为浅灰色
@Input('highlight') bgColor = ‘’;
constructor(private el: ElementRef) {
el.nativeElement.style.customProperty = true;
}
ngOnChanges() {
this.el.nativeElement.style.backgroundColor = this.bgColor || this.defaultColor;
}
}
在下面 TestHost
这个组件里,测试 HighlightDirective
指令:
@Component({
template: `<h2 highlight="skyblue">国学</h2>
<h3>今日经典:</h3>
<q>学而时习之,不亦乐乎。</q>`
})
class TestHostComponent {}
现在就可以写单元测试,验证 h2
元素是否添加了 highlight
指令,并设置了正确的背景颜色。
describe('HighlightDirective', () => {
let container: HTMLElement;
beforeEach(() => {
const fixture = TestBed.configureTestingModule({
declarations: [ TestHostComponent, HighlightDirective ]
})
.createComponent(TestHostComponent);
fixture.detectChanges();
container = fixture.nativeElement.querySelector('h2’);
});
it('should have skyblue <h2>', () => {
const bgColor = container.style.backgroundColor;
expect(bgColor).toBe('skyblue’);
});
测试报表页面:
指令测试报表页面测试表单
表单是 Angular 应用的重要组成部分,很少有应用不包含一个表单的。我们使用下面的查询表单,介绍如何对表单进行单元测试。
<form [formGroup]="searchForm" (ngSubmit)="search()”>
<input type="text" placeholder="请输入用户名" formControlName=“searchText”>
<button type="submit" [disabled]="searchForm.invalid">查询</button>
</form>
组件类定义如下:
import { Component, OnInit } from '@angular/core’;
import { FormControl, FormGroup, Validators } from '@angular/forms’;
@Component({
selector: 'app-search’,
templateUrl: './search.component.html’,
styleUrls: ['./search.component.css’]
})
export class SearchComponent implements OnInit {
get searchText(): FormControl {
return this.searchForm.controls.searchText as FormControl;
}
searchForm = new FormGroup({
searchText: new FormControl('', Validators.required)
});
search() {
if(this.searchForm.valid) {
console.log(‘查询内容是: ' + this.searchText.value)
}
}
constructor() { }
ngOnInit(): void {
}
}
这里,我们要测试三个地方:
-
searchText
属性的设置是否正确 -
查询
按钮禁用状态是否正确 -
console.log
是否调用正确
编写测试用例如下:
describe('SearchComponent', () => {
let component: SearchComponent;
let button: HTMLButtonElement;
let fixture: ComponentFixture<SearchComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [ SearchComponent ],
imports: [ReactiveFormsModule]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(SearchComponent);
component = fixture.componentInstance;
fixture.detectChanges();
button = fixture.nativeElement.querySelector('button’);
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should set the searchText', () => {
const input: HTMLInputElement = fixture.nativeElement.querySelector('input’);
input.value = ‘Angular’;
input.dispatchEvent(newEvent('input’));
expect(component.searchText.value).toBe('Angular’);
});
it('should disable search button', () => {
component.searchText.setValue(‘’);
expect(button.disabled).toBeTrue();
});
it('should log to the console', () => {
const spy = spyOn(console, 'log’);
component.searchText.setValue('Angular’);
fixture.detectChanges();
button.click();
expect(spy.calls.first().args[0]).toBe('查询内容是: Angular’);
});
});
在第一个测试用例中,使用 nativeElement
属性的 querySelector
方法,定位到 input
元素,并设置该元素的值为 Angular
. 接着,调用 input
元素的 dispatchEvent
方法,通知 Angular 框架,input
元素的值已经发生变化。最后,验证组件类的 searchText
属性值是否接收到了 input
元素的值。
在第二个测试用例中,首先,设置 input
元素的值为空。然后,验证查询按钮处于禁用状态。
在第三个测试用例中,首先,设置 input
元素的值为 Angular
。然后,触发变化通知。接着,模拟按钮点击操作。最后,使用 Spying 方法,对输出到控制台到内容进行验证。
测试报表页面:
表单测试报表页面
网友评论