2

I'm trying to mock a file reader, and I have a function that accepts a callback, but during the test, the line where the callback is called is not covered. How can this be solved?

function:

const testFunction = (uint8arr, callback) => { const bb = new Blob([uint8arr]); const f = new FileReader(); f.onload = function (e) { callback(e.target.result); }; f.readAsText(bb); }; module.exports = { testFunction }; 

test:

const { testFunction } = require("./index"); class FileReaderMock { DONE = FileReader.DONE; EMPTY = FileReader.EMPTY; LOADING = FileReader.LOADING; readyState = 0; error = null; result = null; abort = jest.fn(); addEventListener = jest.fn(); dispatchEvent = jest.fn(); onabort = jest.fn(); onerror = jest.fn(); onload = jest.fn(); onloadend = jest.fn(); onloadprogress = jest.fn(); onloadstart = jest.fn(); onprogress = jest.fn(); readAsArrayBuffer = jest.fn(); readAsBinaryString = jest.fn(); readAsDataURL = jest.fn(); readAsText = jest.fn(); removeEventListener = jest.fn(); } const mockCallback = jest.fn(); describe("testFunction", () => { const fileReader = new FileReaderMock(); jest.spyOn(window, "FileReader").mockImplementation(() => fileReader); it("should be called mockCallback and readAsText with the blob value", () => { const uintArray = new Uint8Array(); testFunction(uintArray, mockCallback); // expect(mockCallback).toHaveBeenCalled(); // expect(fileReader.readAsText).toHaveBeenCalledWith(new Blob([uintArray])); }); }); 

codesandbox: https://codesandbox.io/s/jest-test-forked-ecejb?file=/index.test.js

1 Answer 1

1

You can use the getter and setter of the Object.defineProperty() method to intercept the assignment operation of the onload function, so you can get the onload function to test it as usual.

E.g.

index.js:

const testFunction = (uint8arr, callback) => { const bb = new Blob([uint8arr]); const f = new FileReader(); f.onload = function (e) { callback(e.target.result); }; f.readAsText(bb); }; module.exports = { testFunction }; 

index.test.js:

const { testFunction } = require('./index'); describe('testFunction', () => { it('should be called mockCallback and readAsText with the blob value', () => { const mockCallback = jest.fn(); const fileReader = { readAsText: jest.fn(), }; let onloadRef; Object.defineProperty(fileReader, 'onload', { get() { return this._onload; }, set(onload) { onloadRef = onload; this._onload = onload; }, }); jest.spyOn(window, 'FileReader').mockImplementation(() => fileReader); const uintArray = new Uint8Array(); testFunction(uintArray, mockCallback); // onload test const event = { target: { result: 'teresa teng' } }; onloadRef(event); expect(mockCallback).toBeCalledWith('teresa teng'); expect(fileReader.readAsText).toBeCalledWith(new Blob([uintArray])); }); }); 

unit test result:

 PASS examples/66964346/index.test.js (7.479 s) testFunction ✓ should be called mockCallback and readAsText with the blob value (4 ms) ----------|---------|----------|---------|---------|------------------- File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s ----------|---------|----------|---------|---------|------------------- All files | 100 | 100 | 100 | 100 | index.js | 100 | 100 | 100 | 100 | ----------|---------|----------|---------|---------|------------------- Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 8.575 s, estimated 9 s 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.