尝试在 Jasmine 中测试一个函数,该函数 returns `期待一个间谍但得到了一个函数`
Trying to test a function in Jasmine which returns `expected a spy but got a function`
该代码主要用于仅接受 SVG 的缩略图上传器。问题出在 new FileReader() 和 new Image() 上。执行时无法理解错误 Expected a spy but got a function
。我正在尝试 test.The 的功能是针对 NgbModal 的,它显示的目的是为了预览上传 thumbnail.The 上传的缩略图首先加载到模态上,然后加载到组件上
onFileChanged(file: File): void {
this.uploadedImageMimeType = file.type;
this.invalidImageWarningIsShown = false;
this.invalidTagsAndAttributes = {
tags: [],
attrs: []
};
if (this.isUploadedImageSvg()) {
let reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () =>{
this.imgSrc = reader.result as string;
this.updateBackgroundColor(this.tempBgColor);
this.img = new Image();
this.img.onload = () => {
// Setting a default height of 300px and width of
// 150px since most browsers use these dimensions
// for SVG files that do not have an explicit
// height and width defined.
this.setImageDimensions(
this.img.naturalHeight || 150,
this.img.naturalWidth || 300);
};
this.img.src = this.imgSrc;
this.uploadedImage = this.imgSrc;
this.invalidTagsAndAttributes = (
this.svgSanitizerService.getInvalidSvgTagsAndAttrsFromDataUri(
this.imgSrc));
this.tags = this.invalidTagsAndAttributes.tags;
this.attrs = this.invalidTagsAndAttributes.attrs;
if (this.tags.length > 0 || this.attrs.length > 0) {
this.reset();
}
};
} else {
this.reset();
this.invalidImageWarningIsShown = true;
}
}
我为它写的测试
class MockImageObject {
source = null;
onload = null;
constructor() {
this.onload = () => {
return 'Fake onload executed';
};
}
set src(url) {
this.onload();
}
}
class MockReaderObject {
result = null;
onload = null;
constructor() {
this.onload = () => {
return 'Fake onload executed';
};
}
readAsDataURL(file) {
this.onload();
return 'The file is loaded';
}
}
it('should load a image file in onchange event and save it if it\'s a' +
' svg file', fakeAsync(() => {
// This is just a mocked base 64 in order to test the FileReader event
// and its result property.
const dataBase64Mock = 'PHN2ZyB4bWxucz0iaHR0cDo';
const arrayBuffer = Uint8Array.from(
window.atob(dataBase64Mock), c => c.charCodeAt(0));
const file = new File([arrayBuffer], 'thumbnail.png', {
type: 'image/svg+xml'
});
component.uploadedImageMimeType = file.type;
component.invalidImageWarningIsShown = false;
component.invalidTagsAndAttributes = {
tags: [],
attrs: []
};
// This throws "Argument of type 'mockReaderObject' is not assignable to
// parameter of type 'HTMLImageElement'.". This is because
// 'HTMLImageElement' has around 250 more properties. We have only defined
// the properties we need in 'mockReaderObject'.
// @ts-expect-error
spyOn(window, 'FileReader').and.returnValue(new MockReaderObject());
const image = document.createElement('img');
spyOn(window, 'Image').and.returnValue(image);
// This throws "Argument of type 'mockImageObject' is not assignable to
// parameter of type 'HTMLImageElement'.". This is because
// 'HTMLImageElement' has around 250 more properties. We have only defined
// the properties we need in 'mockImageObject'.
// @ts-expect-error
spyOn(window, 'Image').and.returnValue(new mockImageObject());
// ---- Dispatch on load event ----
image.dispatchEvent(new Event('load'));
expect(component.invalidImageWarningIsShown).toBe(false);
component.onInvalidImageLoaded();
expect(component.invalidImageWarningIsShown).toBe(true);
component.onFileChanged(file);
// ---- Dispatch on load event ----
expect(component.invalidTagsAndAttributes).toEqual({
tags: [],
attrs: []
});
expect(component.uploadedImage).toBe(null);
expect(component.invalidImageWarningIsShown).toBe(false);
// ---- Save information ----
component.confirm();
expect(component.confirm).toHaveBeenCalled();
}));
非常感谢任何帮助!
问题是下面语句中的component.confirm
不是Spy
而是一个函数。
expect(component.confirm).toHaveBeenCalled();
see toHaveBeenCalled(expected)
in Jasmine documentation.
解决方案
在此行前面的某处,您需要创建一个Spy
,如下所示:
spyOn(component, 'confirm').and.callThrough();
Please note however that this expect
will never fail since you explicitly invoke component.confirm()
in your test in the line before.
该代码主要用于仅接受 SVG 的缩略图上传器。问题出在 new FileReader() 和 new Image() 上。执行时无法理解错误 Expected a spy but got a function
。我正在尝试 test.The 的功能是针对 NgbModal 的,它显示的目的是为了预览上传 thumbnail.The 上传的缩略图首先加载到模态上,然后加载到组件上
onFileChanged(file: File): void {
this.uploadedImageMimeType = file.type;
this.invalidImageWarningIsShown = false;
this.invalidTagsAndAttributes = {
tags: [],
attrs: []
};
if (this.isUploadedImageSvg()) {
let reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () =>{
this.imgSrc = reader.result as string;
this.updateBackgroundColor(this.tempBgColor);
this.img = new Image();
this.img.onload = () => {
// Setting a default height of 300px and width of
// 150px since most browsers use these dimensions
// for SVG files that do not have an explicit
// height and width defined.
this.setImageDimensions(
this.img.naturalHeight || 150,
this.img.naturalWidth || 300);
};
this.img.src = this.imgSrc;
this.uploadedImage = this.imgSrc;
this.invalidTagsAndAttributes = (
this.svgSanitizerService.getInvalidSvgTagsAndAttrsFromDataUri(
this.imgSrc));
this.tags = this.invalidTagsAndAttributes.tags;
this.attrs = this.invalidTagsAndAttributes.attrs;
if (this.tags.length > 0 || this.attrs.length > 0) {
this.reset();
}
};
} else {
this.reset();
this.invalidImageWarningIsShown = true;
}
}
我为它写的测试
class MockImageObject {
source = null;
onload = null;
constructor() {
this.onload = () => {
return 'Fake onload executed';
};
}
set src(url) {
this.onload();
}
}
class MockReaderObject {
result = null;
onload = null;
constructor() {
this.onload = () => {
return 'Fake onload executed';
};
}
readAsDataURL(file) {
this.onload();
return 'The file is loaded';
}
}
it('should load a image file in onchange event and save it if it\'s a' +
' svg file', fakeAsync(() => {
// This is just a mocked base 64 in order to test the FileReader event
// and its result property.
const dataBase64Mock = 'PHN2ZyB4bWxucz0iaHR0cDo';
const arrayBuffer = Uint8Array.from(
window.atob(dataBase64Mock), c => c.charCodeAt(0));
const file = new File([arrayBuffer], 'thumbnail.png', {
type: 'image/svg+xml'
});
component.uploadedImageMimeType = file.type;
component.invalidImageWarningIsShown = false;
component.invalidTagsAndAttributes = {
tags: [],
attrs: []
};
// This throws "Argument of type 'mockReaderObject' is not assignable to
// parameter of type 'HTMLImageElement'.". This is because
// 'HTMLImageElement' has around 250 more properties. We have only defined
// the properties we need in 'mockReaderObject'.
// @ts-expect-error
spyOn(window, 'FileReader').and.returnValue(new MockReaderObject());
const image = document.createElement('img');
spyOn(window, 'Image').and.returnValue(image);
// This throws "Argument of type 'mockImageObject' is not assignable to
// parameter of type 'HTMLImageElement'.". This is because
// 'HTMLImageElement' has around 250 more properties. We have only defined
// the properties we need in 'mockImageObject'.
// @ts-expect-error
spyOn(window, 'Image').and.returnValue(new mockImageObject());
// ---- Dispatch on load event ----
image.dispatchEvent(new Event('load'));
expect(component.invalidImageWarningIsShown).toBe(false);
component.onInvalidImageLoaded();
expect(component.invalidImageWarningIsShown).toBe(true);
component.onFileChanged(file);
// ---- Dispatch on load event ----
expect(component.invalidTagsAndAttributes).toEqual({
tags: [],
attrs: []
});
expect(component.uploadedImage).toBe(null);
expect(component.invalidImageWarningIsShown).toBe(false);
// ---- Save information ----
component.confirm();
expect(component.confirm).toHaveBeenCalled();
}));
非常感谢任何帮助!
问题是下面语句中的component.confirm
不是Spy
而是一个函数。
expect(component.confirm).toHaveBeenCalled();
see
toHaveBeenCalled(expected)
in Jasmine documentation.
解决方案
在此行前面的某处,您需要创建一个Spy
,如下所示:
spyOn(component, 'confirm').and.callThrough();
Please note however that this
expect
will never fail since you explicitly invokecomponent.confirm()
in your test in the line before.