[英]How to mock FileReader using jest
我需要使用玩笑來模擬使用FileReader
的 function。 特別是 function readAsBinaryString
和onload
。
我創建了一些代碼:
FileReader.readAsBinaryString = () => mock.mockReturnValue(null);
但它不起作用。 如何使用 jest 模擬FileReader
和您的函數?
Function 進行測試:
handleFileUpload(event) {
let reader = new FileReader();
let file = event.target.files[0];
reader.readAsBinaryString(file);
reader.onload = () => {
let base64String = btoa(reader.result);
this.object.image =
};
},
您可以使用jest.spyOn(object, methodName, accessType?)來監視FileReader
的readAsBinaryString
方法。 readAsBinaryString
是一個實例方法,而不是FileReader
構造函數的 static 方法。 此外, readAsBinaryString
的返回值為void
。 所以你不能模擬一個返回值。
例如
index.ts
:
export function main() {
const fr = new FileReader();
const blob = new Blob();
fr.readAsBinaryString(blob);
}
index.spec.ts
,我們需要監視FileReader.prototype.readAsBinaryString
,因為它是一個實例方法。
import { main } from './';
describe('main', () => {
test('should mock FileReader', () => {
const readAsBinaryStringSpy = jest.spyOn(FileReader.prototype, 'readAsBinaryString');
main();
expect(readAsBinaryStringSpy).toBeCalledWith(new Blob());
});
});
覆蓋率 100% 的單元測試結果:
PASS src/stackoverflow/58644737/index.spec.ts
main
✓ should mock FileReader (10ms)
----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
index.ts | 100 | 100 | 100 | 100 | |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 4.852s, estimated 9s
更新
index.ts
:
export class Component {
object = {
image: ''
};
handleFileUpload(event) {
let reader = new FileReader();
let file = event.target.files[0];
reader.readAsBinaryString(file);
reader.onload = () => {
let base64String = btoa(reader.result as string);
this.object.image = base64String;
};
return reader;
}
}
index.spec.ts
:
import { Component } from './';
const cmp = new Component();
describe('main', () => {
beforeEach(() => {
jest.restoreAllMocks();
});
test('should test handle file upload correctly', () => {
const mFile = new File(['go'], 'go.pdf');
const mEvent = { target: { files: [mFile] } };
const readAsBinaryStringSpy = jest.spyOn(FileReader.prototype, 'readAsBinaryString');
const btoaSpy = jest.spyOn(window, 'btoa');
const reader = cmp.handleFileUpload(mEvent);
expect(reader).toBeInstanceOf(FileReader);
if (reader.onload) {
Object.defineProperty(reader, 'result', { value: 'gogo' });
const mOnloadEvent = {} as any;
reader.onload(mOnloadEvent);
expect(btoaSpy).toBeCalledWith('gogo');
expect(cmp.object.image).toBe(btoa('gogo'));
}
expect(readAsBinaryStringSpy).toBeCalledWith(mFile);
});
});
覆蓋率 100% 的單元測試結果:
PASS src/stackoverflow/58644737/index.spec.ts (7.328s)
main
✓ should test handle file upload correctly (13ms)
----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
index.ts | 100 | 100 | 100 | 100 | |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 8.78s
源碼: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/58644737
我已經取得了一些進展:
const dummy = {
readAsBinaryString: jest.fn(),
onload: function(){
wrapper.vm.object.image = '...'
}
}
}
window.FileReader = jest.fn(() => dummy)
問題是 onload 在實際調用時不會被嘲笑:
reader.onload = function() {
}
只有當我打電話
reader.onload()
所以我認為對 dummy 的 onload 聲明是錯誤的。
我個人無法在我的 Vue-test-utils 設置jest.spyOn(FileReader.prototype, 'readAsDataURL');
不斷產生以下錯誤: Cannot spy the readAsDataURL property because it is not a function; undefined given instead
Cannot spy the readAsDataURL property because it is not a function; undefined given instead
如果它可以幫助其他有此問題的人,我設法使用以下方法成功地模擬了 FileReader 原型:
Object.defineProperty(global, 'FileReader', {
writable: true,
value: jest.fn().mockImplementation(() => ({
readAsDataURL: jest.fn(),
onLoad: jest.fn()
})),
})
然后在我的測試中,我能夠通過 mocking 事件測試文件輸入 onChange 方法(使用 FileReader)並像這樣手動觸發它:
const file = {
size: 1000,
type: "audio/mp3",
name: "my-file.mp3"
}
const event = {
target: {
files: [file]
}
}
wrapper.vm.onChange(event)
很晚的評論,但就其價值而言,這就是我能夠模擬 FileReader 的方式:
首先,我創建了一個返回 new FileReader() 而不是直接調用它的 function。
export function fileReaderWrapper() {
return new FileReader();
}
那么需要文件閱讀器的代碼可以調用那個function
const reader = fileReaderWrapper();
reader.readAsDataURL(file);
while (reader.readyState !== 2) {
yield delay(100);
}
const imageData = reader.result;
現在我的測試可以使用 jest 來模擬我檢查的所有內容。我不再需要在測試中使用超時來等待 FileReader 完成讀取文件。
jest.mock('~/utils/helper', () => ({
fileReaderWrapper: jest.fn().mockReturnValue({
readAsDataURL: (file: File) => {
return;
},
readyState: 2,
result: 'data:image/png;base64,undefined',
}),
}));
如果你想調用 onload 事件作為 readAsText 的一部分你可以使用下面的代碼
const readAsTextMock = jest.fn();
jest.spyOn(global, 'FileReader').mockImplementation(function () {
const self = this;
this.readAsText = readAsTextMock.mockImplementation(() => {
self.onload({ target: { result: "file read result mock" } });
});
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.