咱们在进行单元测试时,尽量的将每一个功能点拆分红独立的可测试的小功能。力求测试点的最小化。这样不只测试时减小思惟量,也使得对测试代码的修正简单。有时当咱们没法对某个函数是否执行进行测试时,咱们就须要用到间谍函数。dom
情景引入async
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()方法。ide
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方法就像一个间谍,监听指定的方法,当有人调用这个方法时,截取他,让他不调用真正的方法,当调用此方法时实际上调用的为该方法的替身。测试
咱们除了能够方法构造替身外,还能够对类构造替身this
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。
当咱们使用时spa
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>类型。code
咱们在测试时要善于使用方法进行测试,能够用替身的,坚定不用真身。component