前言
我们在进行单元测试时,尽可能的将每个功能点拆分成独立的可测试的小功能。力求测试点的最小化。这样不仅测试时减少思维量,也使得对测试代码的修正简单。有时当我们无法对某个函数是否执行进行测试时,我们就需要用到间谍函数。
例子
情景引入
ngOnInit() {
this.loadData();
}
/*查询*/
onQuery() {
this.loadData(); // 直接调用数据加载函数
}
loadData() {
const queryParams = {
page: this.params.page,
size: this.params.size,
klassId: this.params.klass.id,
name: this.params.name.value,
sno: this.params.sno.value
};
...
}
当我们本着不造重复的轮子的原则对ngOnInit方法和onQuery方法相同部分写到一个方法里,再分别进行调用时。我们发现测试变成了loadData是否正确执行和ngOnInit方法和onQuery方法是否正确调用loadData方法两步,而后者如何进行测试呢?angular为我们提供了spyOn()方法。
替身方法
spyon方法使用方法如下
spyOn(Math, 'random').andReturn(0.1);
spyon有监听的意思,这句话的意思是说,当我们调用math类的random方法时,返回0.1.
回到我们的测试中来,我们可以这样测试onQuery方法是否调用了loadData方法
describe('Student -> IndexComponent', () => {
...
fit('onQuery', () => {
spyOn(component, 'loadData');
component.onQuery();
expect(component.loadData).toHaveBeenCalled();
});
});
我们对loadData方法进行监听,一旦被调用,我们就可以通过断言判别。
spyOn方法就像一个间谍,监听指定的方法,当有人调用这个方法时,截取他,让他不调用真正的方法,当调用此方法时实际上调用的为该方法的替身。
替身类
我们除了可以方法构造替身外,还可以对类构造替身
beforeEach(async(() => {
const routerSpy = jasmine.createSpyObj<Router>('Router', ['navigateByUrl']);
TestBed.configureTestingModule({
declarations: [EditComponent],
imports: [
ReactiveFormsModule,
HttpClientTestingModule,
RouterTestingModule
],
providers: [
{provide: ActivatedRoute, useClass: ActivatedRouteStub},
{provide: Router, useValue: routerSpy}
]
})
.compileComponents();
}));
他创建了一个router的替身,并且该替身含有navigateByUrl方法。这时我们需要在providers中进行声明,当调用Router时,用routerSpy。
当我们使用时
fit(‘', () => {
...
const routerSpy: SpyObj<Router> = TestBed.get(Router);
expect(routerSpy.navigateByUrl.calls.any()).toBe(false);
req.flush(null, {status: 204, statusText: 'No Content'});
expect(routerSpy.navigateByUrl.calls.any()).toBe(true);
});
在调用时,我们需要先获取替身。我们定义时声明为SpyObj<Router>类型,在使用时也应是SpyObj<Router>类型。
总结
我们在测试时要善于使用方法进行测试,可以用替身的,坚决不用真身。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。