gpt4 book ai didi

angular 4.3.0 在执行异步函数后调用 fixture.whenStable

转载 作者:太空狗 更新时间:2023-10-29 17:57:06 30 4
gpt4 key购买 nike

我正在为一个应用程序编写 jasmine/karma/webpack 单元测试,其中有很多内部 promise 在代码深处得到解决。我想使用 Angular 的异步、fixture.detectChanges 和 fixture.whenStable。

作为概念证明,我制作了以下简单但非常异步的组件。

import {Component} from "@angular/core";
import {Logger} from "../../utils/logger";

@Component({
selector: 'unit-test.html',
template: `
<div class="unit-test">
<h3>Unit Test Component</h3>
<h4>p1: {{p1}}</h4>
<h4>v1: {{v1}}</h4>
<h4>p2: {{p2}}</h4>
<h4>v2: {{v2}}</h4>
<h4>p3: {{p3}}</h4>
<h4>v3: {{v3}}</h4>
</div>`
})
export class UnitTestComponent {
p1: Promise<string>;
v1: string;
p2: Promise<string>;
v2: string;
p3: Promise<string>;
v3: string;

constructor() {
this.p1 = makeTimeoutPromise('value1', 2000);
Logger.warn('p1 created');
this.p1.then(data => {
this.v1 = data
});
}

method2() {
this.p2 = makeTimeoutPromise('value2', 2000);
this.p2.then(data => {
this.v2 = data
});
Logger.warn('p2 created');
}

method3() {
this.p3 = makeTimeoutPromise('value3', 2000);
this.p3.then(data => {
this.v3 = data
});
Logger.warn('p2 created');
}
}


function makeTimeoutPromise(result: string, timeout: number) {
return new Promise<string>((resolve, reject) => {
setTimeout(() => {
resolve(result);
Logger.warn(`resolved '${result}' after '${timeout}' seconds`);
}, timeout)
});
}

为了对此进行测试,我在异步 block 中创建了组件。这有效,并且 it block 在构造函数的 promise 已解决后开始运行。

在测试中,我调用了 comp.method2() ,这导致 promise 在 2 秒后得到解决。然而……这是我没有得到的部分……在调用 comp.method2() 返回 true 后立即调用 fixture.isStable()。我本来以为是假的。更糟的是... fixture.whenStable() 立即解析。由于实际方法中的 promise 尚未解决,因此我还没有要测试的值。

import {UnitTestComponent} from './unit-test.component';
import {async, ComponentFixture, TestBed, tick} from '@angular/core/testing';
import {DebugElement} from '@angular/core';

describe('UnitTestComponent', () => {
let de: DebugElement;
let comp: UnitTestComponent;
let fixture: ComponentFixture<UnitTestComponent>;
let el: HTMLElement;
const startTime = Date.now();
beforeEach(async(() => {
console.log('time beforeEach.start', Date.now() - startTime);
const testbed = TestBed.configureTestingModule({
declarations:[UnitTestComponent],
imports: [],
providers: []
});
// testbed.compileComponents();
console.log('time beforeEach.initSsmpComponentLibModule', Date.now() - startTime);
fixture = TestBed.createComponent(UnitTestComponent);
comp = fixture.componentInstance;
de = fixture.debugElement;
console.log('time beforeEach.end', Date.now() - startTime);
}));

it('should create the component', async(() => {
// const x = new Promise<any>((resolve, reject)=>{
// setTimeout(()=>{
// console.log('right before exit', comp);
// fixture.detectChanges();
// resolve();
// }, 10000);
// });
console.log('time it.start', Date.now() - startTime, comp);
expect(comp).toBeDefined();
console.log('fixture.isStable() (1)', fixture.isStable());
comp.method2();
console.log('fixture.isStable() (2)', fixture.isStable());
fixture.whenStable()
.then(data=>{
fixture.detectChanges();
console.log('time after whenStable(1) resolves', Date.now() - startTime, comp);
fixture.detectChanges();
console.log('time after whenStable(1).detect changes completes', Date.now() - startTime, comp);
expect(comp.v2).toBe('value2');
comp.method3();
console.log('method3 called', Date.now() - startTime, comp);
fixture.detectChanges();
console.log('time after detectChanges (2)', Date.now() - startTime, comp);
fixture.whenStable()
.then(data=>{
fixture.detectChanges();
console.log('time after whenStable(3).then', Date.now() - startTime, comp);
expect(comp.v3).toBe('value3');
});
console.log('time after whenStable(3)', Date.now() - startTime, comp);

});
console.log('time after whenStable(2)', Date.now() - startTime, comp);
}));


});

控制台日志输出如下。我期待着

fixture.isStable() (2) false
time after whenStable(2) >=4386 UnitTestComponent {p1: ZoneAwarePromise, v1: "value1", p2: ZoneAwarePromise}

但是得到了

fixture.isStable() (2) true
time after whenStable(2) 2390 UnitTestComponent {p1: ZoneAwarePromise, v1: "value1", p2: ZoneAwarePromise}

time beforeEach.start 363
time beforeEach.initSsmpComponentLibModule 363
time beforeEach.end 387
time it.start 2386 UnitTestComponent {p1: ZoneAwarePromise, v1: "value1"}
fixture.isStable() (1) true
fixture.isStable() (2) true
time after whenStable(2) 2390 UnitTestComponent {p1: ZoneAwarePromise, v1: "value1", p2: ZoneAwarePromise}
time after whenStable(1) resolves 2393 time beforeEach.start 363

如果不明确了解 comp.method2() 的内部结构,我怎么能有 Angular 等待,直到所有 promise 从 it() 方法内部调用的方法解析?我认为这是 fixture.whenStable 的明确作用。

最佳答案

回答我自己的问题。当然!我没有在一个区域中运行。所以有两种方法可以解决这个问题。 (我证明了两者)。

解决方案 1:获取 native 元素并单击它......如果您正在测试浏览器事件。 (所以我加了

<button id='unit-test-method-2-button'(click)="method2()">Method 2</button>

然后调用 method2() 使用

const button = de.query(By.css('#unit-test-method-2-button'));
expect(button).toBeDefined();
button.nativeElement.click();

满足我需求的更好解决方案是简单地注入(inject) NgZone。这允许我对 fixture.whenStable() 进行嵌套调用。

因此我添加了

beforeEach(inject([NgZone], (injectedNgZone: NgZone) => {
ngZone = injectedNgZone;
}));

这让我可以调用异步方法 2,然后调用异步方法 3,并使用 fixture.whenStable...

it('should create the component', async(() => {
ngZone.run(() => {
console.log('time it.start', Date.now() - startTime, comp);
expect(comp).toBeDefined();
expect(fixture.isStable()).toBe(true, 'expect fixture to be stable');
comp.method2();
expect(fixture.isStable()).toBe(false, 'expect fixture not to be stable');
fixture.whenStable()
.then(data => {
fixture.detectChanges();
expect(comp.v2).toBe('value2');
comp.method3();
fixture.whenStable()
.then(data => {
fixture.detectChanges();
expect(comp.v3).toBe('value3');
});
});
});
}));

关于angular 4.3.0 在执行异步函数后调用 fixture.whenStable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45123145/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com