咱們在進行單元測試時,儘量的將每一個功能點拆分紅獨立的可測試的小功能。力求測試點的最小化。這樣不只測試時減小思惟量,也使得對測試代碼的修正簡單。有時當咱們沒法對某個函數是否執行進行測試時,咱們就須要用到間諜函數。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