【问题标题】:Testing receiving input from other components when using setTimeout使用 setTimeout 测试从其他组件接收输入
【发布时间】:2019-11-21 16:50:54
【问题描述】:

这个问题是上一个问题 (linked here) 的延续。我仍在使用相同的文件,目的是为 Angular 测试编写简单的教程。新问题与 setTimeout 函数有关。

在 ngOnInit 和 ngAfterViewInit 上,我都在实现 setTimeout(我将在未来编写的其他测试这样做,所以这只是为了创建一个基本示例)。里面的函数设置通过 HTML 文件传递​​给子组件的变量的值。然后检查该子组件的变量是否有特定值。

我已经尝试使用 tick(value) 和 fixture.detectChanges() 来尝试触发 setTimeout 函数的内容,但该值仍然未定义(参见代码 sn-ps)。

random.test.component.ts

public dataThatGetsDelayed: any;

constructor() {

}

ngOnInit() {
    setTimeout(() => {
        this.dataThatGetsDelayed = "OnInit";
    }, 100);
}

ngAfterViewInit() {
    setTimeout(() => {
        this.dataThatGetsDelayed = "AfterView";
    }, 100);
}

random.test.component.html

[variableThatStoresDelayedData]="dataThatGetsDelayed"

random.test.component.child.ts

@Input() variableThatStoresDelayedData: any;

random.test.file.spec.ts

it('Testing if receiving input works properly with a time delay in ngOnInit', fakeAsync(() => {
    const componentInThePage: TestComponentChild = fixture.debugElement.query(By.directive(TestComponentChild)).componentInstance;
    expect(componentInThePage).toBeTruthy();

    tick(100);
    fixture.detectChanges();

    fixture.whenStable().then(() => {
        expect(componentInThePage.variableThatStoresDelayedData).toEqual("OnInit");
    });
}));

it('Testing if receiving input works properly with a time delay in ngAfterViewInit', fakeAsync(() => {
    const componentInThePage: TestComponentChild = fixture.debugElement.query(By.directive(TestComponentChild)).componentInstance;
    expect(componentInThePage).toBeTruthy();

    //tick(100);
    //component.ngAfterViewInit();

    fixture.whenStable().then(() => {
        expect(componentInThePage.variableThatStoresDelayedData).toEqual("AfterView");
    });
}));

我读到我应该在最后使用 whenStable,但我现在知道这完全被忽略了。没有它,我会收到错误“预期未定义等于'OnInit'/'AfterView'”。我省略了第二个刻度,因为它会导致错误“1 timer(s) still in the queue”。

我如何告诉程序等到在 setTimeout 函数中设置值?

【问题讨论】:

    标签: angular typescript unit-testing karma-runner


    【解决方案1】:

    好的,通过一些研究和实验,我找到了解决方案。代码 cmets 解释了更详细的细节:

    random.test.component.ts

    public dataThatGetsDelayed: any = "Initial value"; //This is just to show how the value changes.
    
    constructor(private detectorReference: ChangeDetectorRef) {
        //The detectorReference is used in ngAfterViewInit
    }
    
    ngOnInit() {
        setTimeout(() => {
            this.dataThatGetsDelayed = "OnInit";
        }, 100);
    }
    
    ngAfterViewInit() {
        setTimeout(() => {
            this.dataThatGetsDelayed = "AfterView";
            this.detectorReference.detectChanges(); //Needed to stop the error about changing the value.
        }, 200);
    }
    

    (感谢this源的帮助!)

    random.test.file.spec.ts

    //This test is for the ngOnInit function
    it('Testing if receiving input works properly with a time delay in ngOnInit', fakeAsync(() => {
        const componentInThePage: TestComponentChild = fixture.debugElement.query(By.directive(TestComponentChild)).componentInstance;
        expect(componentInThePage).toBeTruthy();
    
        expect(componentInThePage.variableThatStoresDelayedData).toEqual("Initial value");
    
        component.ngOnInit();
        //tick(99); - This doesn't /quite/ run out the setTimeout function from the ngOnInit function.
        tick(100); //This does, though.
        fixture.detectChanges();
    
        expect(componentInThePage.variableThatStoresDelayedData).toEqual("OnInit");
    }));
    
    //This test is for the ngAfterViewInit function. Note that the value isn't set with ngOnInit first;
    //only the explicit method call will perform the desired action.
    it('Testing if receiving input works properly with a time delay in ngAfterViewInit', fakeAsync(() => {
        const componentInThePage: TestComponentChild = fixture.debugElement.query(By.directive(TestComponentChild)).componentInstance;
        expect(componentInThePage).toBeTruthy();
    
        expect(componentInThePage.variableThatStoresDelayedData).toEqual("Initial value");
    
        component.ngAfterViewInit();
        //tick(199); - Again, this doesn't /quite/ run out the setTimeout.
        tick(200); //But, once again, this does.
        fixture.detectChanges();
    
        expect(componentInThePage.variableThatStoresDelayedData).toEqual("AfterView");
    }));
    

    希望这对将来的某人有所帮助!

    【讨论】:

      猜你喜欢
      • 2020-11-19
      • 2018-11-03
      • 2022-01-05
      • 2023-03-21
      • 2016-12-06
      • 2016-11-02
      • 2019-11-19
      • 2020-09-29
      • 2018-02-19
      相关资源
      最近更新 更多