你应该使用fakeAsync()和tick().查看下面的代码(.spec.ts文件),该代码根据您的测试代码成功运行.
下面的代码说明:
fakeAsync()
并且tick()
应始终一起使用.您可以async()/fixtureInstance.whenStable()
一起使用,但从程序员的角度来看,它不那么"可预测".我会建议你随时使用fakeAsync()/tick()
.你应该只使用async()/fixtureInstance.whenStable()
你的测试代码,使一个XHR调用(又名测试Http请求)时.
最好尽可能使用fakeAsync()/tick()
,因为您可以手动控制异步代码在测试代码中的运行方式.
正如您在下面的代码中看到的那样(.spec.ts文件).为您调用该方法的参数刻度方法是非常重要的300
,tick(300)
因为你设置的反跳值300
.如果您假设将去抖动值设置为500
,那么您的刻度值应该500
在您的测试代码中,如果您希望它在这种情况下通过.
您会注意到,如果您设置tick(299)
测试将失败,但这是正确的,因为您将去抖动值设置为300
.这向您展示了使用的强大功能fakeAsync()/tick()
,您可以控制您的代码时间(当您使用时,您是时间大师fakeAsync()/tick()
).
// component.sandbox.spec.ts import { async, TestBed, fakeAsync, tick, inject } from "@angular/core/testing"; import { ReactiveFormsModule } from "@angular/forms"; import { SandboxComponent } from "./component.sandbox"; import { ItemService } from "../../Providers"; import "rxjs/add/operator/debounceTime"; describe("testFormControl", () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [ReactiveFormsModule], declarations: [SandboxComponent], providers: [ItemService], }).compileComponents(); })); // The test you had questions about :) it("(fakeAsync usage) Should hit the ItemService instance's 'update' method once", fakeAsync(inject([ItemService], (itemService: ItemService) => { spyOn(itemService, "update"); let fixture = TestBed.createComponent(SandboxComponent); fixture.detectChanges(); // It is best practices to call this after creating the component b/c we want to have a baseline rendered component (with ng2 change detection triggered) after we create the component and trigger all of its lifecycle events of which may cause the need for change detection to occur, in the case attempted template data bounding occurs. let componentUnderTest = fixture.componentInstance; componentUnderTest.saveItem("someValueIWantToSaveHEHEHE"); tick(300); // avoliva :) expect(itemService.update).toHaveBeenCalled(); }))); });
// component.sandbox.ts import { Component, OnInit } from "@angular/core"; import { FormGroup, FormControl } from "@angular/forms"; import { ItemService } from "../../Providers"; @Component({ template: ``, styleUrls: ["component.sandbox.scss"], }) export class SandboxComponent extends OnInit { public formGroupInstance: FormGroup; public testFormControlInstance: FormControl; constructor(private itemService: ItemService) { super(); this.testFormControlInstance = new FormControl(); this.formGroupInstance = new FormGroup( { testFormControl: this.testFormControlInstance, }, ); } public ngOnInit() { this.testFormControlInstance.valueChanges .debounceTime(300) // avoliva .subscribe((formControlInstanceValue: {}) => { this.itemService.update(formControlInstanceValue); }); } public saveItem(item: any) { this.testFormControlInstance.setValue(item); } }
// ../../Provider/index.ts export class ItemService { public update(formControlInstanceValue: any) { // Makes http request to api to update item console.log(`HEY PROGRAMMER, YEAH YOU! :P \n => http request could have been made here to update an 'item' in the database.`); } }