Angular 6 单元测试 ngOnInit 与 setTimeOut 不工作
Angular 6 Unit Test ngOnInit with a setTimeOut not working
我在 ngOnInit 函数中有一个带有 setTimeOut 函数的组件。为了为此编写单元测试用例,我使用 tick 和 fakeAsync 来快进 setTimeOut。但是,它没有被执行,这反过来又没有调用其他函数 closeAlert()。
组件代码:
export class BannerComponent implements OnInit {
@Input()errorData: any;
@Input()callback: any;
@Input()autoHide: boolean;
constructor() { }
ngOnInit() {
if (this.autoHide) {
setTimeout
(() => {
this.closeAlert();
}, 500);
}
}
closeAlert() {
this.errorData = null;
if (this.callback) {
this.callback();
}
};
}
规格文件:
describe('BannerComponent', () => {
let component: BannerComponent;
let fixture: ComponentFixture<BannerComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ BannerComponent ]
})
.compileComponents();
}));
beforeEach(async() => {
fixture = TestBed.createComponent(BannerComponent);
component = fixture.componentInstance;
component.ngOnInit();
fixture.detectChanges();
});
it("banner should hide after 500ms", fakeAsync(() => {
component.errorData = {
_statusMessage: "New alert banner",
_statusCode: '200',
};
component.callback = null;;
component.autoHide = true;
tick(600);
fixture.detectChanges()
fixture.whenStable().then(() => {
let banner = fixture.debugElement.query(By.css('.success'));
expect(banner).toBe(null)
})
}));
});
Html代码:
<div class="success">
<p>{{errorData._statusMessage}}</p>
</div>
我在代码中发现了几个问题。
- 在
component.errorData
. 中设置有效数据之前,您正在调用 component.ngOnInit()
和 fixture.detectChanges()
(它们也会调用 ngOnInit)
- 我不清楚为什么您期望
banner
与您显示的 html 为空。因此,我将测试更改为查看 component.closeAlert()
是否已被调用,并且 component.errorData
是否已重置为 null,因为看起来这才是您真正想要测试的。为了对此进行测试,我监视了 component.closeAlert()
.
- 我通过在
tick(499)
之后进行测试来设置滴答以准确显示调用 component.closeAlert()
的时间,然后再进行一次滴答...
工作StackBlitz。
代码:
beforeEach(async(() => { // slight correction of incorrect async wrapper ...
fixture = TestBed.createComponent(BannerComponent);
component = fixture.componentInstance;
// component.ngOnInit(); // <-- don't call this here, the data isn't set up yet ...
// fixture.detectChanges(); // ditto
}));
it("banner should hide after 500ms", fakeAsync(() => {
spyOn(component, 'closeAlert').and.callThrough(); // set up a spy so we can test later
component.errorData = {
_statusMessage: "New alert banner",
_statusCode: '200',
};
component.callback = null;;
component.autoHide = true;
fixture.detectChanges(); // <-- this will execute ngOnInit()
expect(component.errorData).not.toBeNull(); // <-- after ngOnInit, still NOT null
expect(component.closeAlert).not.toHaveBeenCalled();
tick(499); // <-- now let 499ms pass ...
expect(component.errorData).not.toBeNull(); // <-- after all that "fake" time, still NOT null
expect(component.closeAlert).not.toHaveBeenCalled();
tick(1); // <-- now tick for just 1 more millisecond ...
expect(component.errorData).toBeNull(); // <-- now this has become NULL
expect(component.closeAlert).toHaveBeenCalled(); // <-- and the method was called
// fixture.whenStable().then(() => {
// let banner = fixture.debugElement.query(By.css('.success'));
// expect(banner).toBe(null)
// });
}));
希望对您有所帮助!
我在 ngOnInit 函数中有一个带有 setTimeOut 函数的组件。为了为此编写单元测试用例,我使用 tick 和 fakeAsync 来快进 setTimeOut。但是,它没有被执行,这反过来又没有调用其他函数 closeAlert()。
组件代码:
export class BannerComponent implements OnInit {
@Input()errorData: any;
@Input()callback: any;
@Input()autoHide: boolean;
constructor() { }
ngOnInit() {
if (this.autoHide) {
setTimeout
(() => {
this.closeAlert();
}, 500);
}
}
closeAlert() {
this.errorData = null;
if (this.callback) {
this.callback();
}
};
}
规格文件:
describe('BannerComponent', () => {
let component: BannerComponent;
let fixture: ComponentFixture<BannerComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ BannerComponent ]
})
.compileComponents();
}));
beforeEach(async() => {
fixture = TestBed.createComponent(BannerComponent);
component = fixture.componentInstance;
component.ngOnInit();
fixture.detectChanges();
});
it("banner should hide after 500ms", fakeAsync(() => {
component.errorData = {
_statusMessage: "New alert banner",
_statusCode: '200',
};
component.callback = null;;
component.autoHide = true;
tick(600);
fixture.detectChanges()
fixture.whenStable().then(() => {
let banner = fixture.debugElement.query(By.css('.success'));
expect(banner).toBe(null)
})
}));
});
Html代码:
<div class="success">
<p>{{errorData._statusMessage}}</p>
</div>
我在代码中发现了几个问题。
- 在
component.errorData
. 中设置有效数据之前,您正在调用 - 我不清楚为什么您期望
banner
与您显示的 html 为空。因此,我将测试更改为查看component.closeAlert()
是否已被调用,并且component.errorData
是否已重置为 null,因为看起来这才是您真正想要测试的。为了对此进行测试,我监视了component.closeAlert()
. - 我通过在
tick(499)
之后进行测试来设置滴答以准确显示调用component.closeAlert()
的时间,然后再进行一次滴答...
component.ngOnInit()
和 fixture.detectChanges()
(它们也会调用 ngOnInit)
工作StackBlitz。
代码:
beforeEach(async(() => { // slight correction of incorrect async wrapper ...
fixture = TestBed.createComponent(BannerComponent);
component = fixture.componentInstance;
// component.ngOnInit(); // <-- don't call this here, the data isn't set up yet ...
// fixture.detectChanges(); // ditto
}));
it("banner should hide after 500ms", fakeAsync(() => {
spyOn(component, 'closeAlert').and.callThrough(); // set up a spy so we can test later
component.errorData = {
_statusMessage: "New alert banner",
_statusCode: '200',
};
component.callback = null;;
component.autoHide = true;
fixture.detectChanges(); // <-- this will execute ngOnInit()
expect(component.errorData).not.toBeNull(); // <-- after ngOnInit, still NOT null
expect(component.closeAlert).not.toHaveBeenCalled();
tick(499); // <-- now let 499ms pass ...
expect(component.errorData).not.toBeNull(); // <-- after all that "fake" time, still NOT null
expect(component.closeAlert).not.toHaveBeenCalled();
tick(1); // <-- now tick for just 1 more millisecond ...
expect(component.errorData).toBeNull(); // <-- now this has become NULL
expect(component.closeAlert).toHaveBeenCalled(); // <-- and the method was called
// fixture.whenStable().then(() => {
// let banner = fixture.debugElement.query(By.css('.success'));
// expect(banner).toBe(null)
// });
}));
希望对您有所帮助!