Angular - 单元测试间谍没有识别出该函数已被调用
Angular - unit test spy are not recognising that the function has been called
我有一个用于测试指令的测试组件:
export class UnitTestComponent implements OnInit {
@ViewChild(BackgroundLoadedDirective) backgroundLoaded: BackgroundLoadedDirective;
public url = 'https://www.codeproject.com/KB/GDI-plus/ImageProcessing2/flip.jpg';
constructor() {}
ngOnInit() {}
loaded(): void {
console.log(true)
}
}
然后我有这个指令,我想为它编写一些测试:
@Directive({
selector: '[backgroundLoaded]'
})
export class BackgroundLoadedDirective {
@Input('backgroundLoaded') set url(value) {
this.createImage(value);
};
get url() {
return this._url;
}
@Output() loaded: EventEmitter<any> = new EventEmitter<any>();
public img: HTMLImageElement;
private _url: string;
@HostBinding('class.background-loaded')
isLoaded = false;
createImage(url: string): void {
// This gets logged as expected
console.log(url);
this._url = url;
this.img = new Image();
this.img.onload = () => {
this.isLoaded = true;
this.load.emit(url);
};
this.img.src = url;
}
}
那么我目前只有这个测试:
describe('BackgroundLoadedDirective', () => {
let component: UnitTestComponent;
let fixture: ComponentFixture<UnitTestComponent>;
let spy: any;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [
UnitTestComponent,
BackgroundLoadedDirective
],
schemas: [NO_ERRORS_SCHEMA],
providers: [
{provide: ComponentFixtureAutoDetect, useValue: true}
]
});
fixture = TestBed.createComponent(UnitTestComponent);
component = fixture.componentInstance;
});
it('should create a fake img tag', () => {
spy = spyOn(component.backgroundLoaded, 'createImage').and.callThrough();
expect(component.backgroundLoaded.img).toBeTruthy();
expect(spy).toHaveBeenCalled();
});
});
问题是测试失败说:
Expected spy createImage to have been called.
尽管调用了该函数,为什么间谍仍不工作?
编辑:
澄清一下,这是测试组件的 html,它应用指令并给它 url。
<div [urlToBackground]="url" [backgroundLoaded]="url" (loaded)="loaded($event)"></div>
基本上干扰的是角度生命周期挂钩。您的测试在时间方面不够关心。
为了更容易测试,触发更改,然后测试您的 setter 是否有效(并调用您正在监视的函数)。
像这样:
it('should create a fake img tag', () => {
let spy: jasmine.Spy = spyOn(component.backgroundLoaded, 'createImage').and.callThrough();
comp.backgroundLoaded.url = 'foobar';
fixture.detectChanges(); // wait for the change detection to kick in
expect(spy).toHaveBeenCalled();
});
希望对您有所帮助。
(编辑:为 ngOnInit
删除了一个 detectChanges()
,因为这里不需要,无论如何应该在测试前调用)
我有一个用于测试指令的测试组件:
export class UnitTestComponent implements OnInit {
@ViewChild(BackgroundLoadedDirective) backgroundLoaded: BackgroundLoadedDirective;
public url = 'https://www.codeproject.com/KB/GDI-plus/ImageProcessing2/flip.jpg';
constructor() {}
ngOnInit() {}
loaded(): void {
console.log(true)
}
}
然后我有这个指令,我想为它编写一些测试:
@Directive({
selector: '[backgroundLoaded]'
})
export class BackgroundLoadedDirective {
@Input('backgroundLoaded') set url(value) {
this.createImage(value);
};
get url() {
return this._url;
}
@Output() loaded: EventEmitter<any> = new EventEmitter<any>();
public img: HTMLImageElement;
private _url: string;
@HostBinding('class.background-loaded')
isLoaded = false;
createImage(url: string): void {
// This gets logged as expected
console.log(url);
this._url = url;
this.img = new Image();
this.img.onload = () => {
this.isLoaded = true;
this.load.emit(url);
};
this.img.src = url;
}
}
那么我目前只有这个测试:
describe('BackgroundLoadedDirective', () => {
let component: UnitTestComponent;
let fixture: ComponentFixture<UnitTestComponent>;
let spy: any;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [
UnitTestComponent,
BackgroundLoadedDirective
],
schemas: [NO_ERRORS_SCHEMA],
providers: [
{provide: ComponentFixtureAutoDetect, useValue: true}
]
});
fixture = TestBed.createComponent(UnitTestComponent);
component = fixture.componentInstance;
});
it('should create a fake img tag', () => {
spy = spyOn(component.backgroundLoaded, 'createImage').and.callThrough();
expect(component.backgroundLoaded.img).toBeTruthy();
expect(spy).toHaveBeenCalled();
});
});
问题是测试失败说:
Expected spy createImage to have been called.
尽管调用了该函数,为什么间谍仍不工作?
编辑:
澄清一下,这是测试组件的 html,它应用指令并给它 url。
<div [urlToBackground]="url" [backgroundLoaded]="url" (loaded)="loaded($event)"></div>
基本上干扰的是角度生命周期挂钩。您的测试在时间方面不够关心。
为了更容易测试,触发更改,然后测试您的 setter 是否有效(并调用您正在监视的函数)。
像这样:
it('should create a fake img tag', () => {
let spy: jasmine.Spy = spyOn(component.backgroundLoaded, 'createImage').and.callThrough();
comp.backgroundLoaded.url = 'foobar';
fixture.detectChanges(); // wait for the change detection to kick in
expect(spy).toHaveBeenCalled();
});
希望对您有所帮助。
(编辑:为 ngOnInit
删除了一个 detectChanges()
,因为这里不需要,无论如何应该在测试前调用)