I’ve been struggling over the past couple of weeks with unit testing a file upload react component with jest. Specifically, I’m trying to test whether or not the method onReadAsDataUrl is being called from FileReader in one of my methods. This is an example method I am testing:
loadFinalImage = async (file) => {
const reader = new FileReader();
reader.onloadend = () => {
this.setState({
imagePreviewUrl: reader.result,
validCard: true,
});
};
await reader.readAsDataURL(file);
}
This is how I am attempting to mock FileReader and test whether or not onReadAsDataUrl has been called:
it('is a valid image and reader.onReadAsDataUrl was called', () => {
const file = new Blob(['a'.repeat(1)], { type: 'image/png' });
wrapper = shallow(<ImageUpload />).dive();
const wrapperInstance = wrapper.instance();
const mockReader = jest.fn();
jest.spyOn('FileReader', () => jest.fn());
FileReader.mockImplementation(() => { return mockReader });
const onReadAsDataUrl = jest.spyOn(mockReader, 'readAsDataURL');
wrapperInstance.loadFinalImage(file);
expect(onReadAsDataUrl).toHaveBeenCalled();
});
After I run: yarn jest
, I get the following test failure:
Cannot spyOn on a primitive value; string given.
I assume I am getting this error because I am not importing FileReader
, but I am not exactly sure how I would import it or mock it because FileReader
is an interface. Here is an image of the test failure:
I am a bit of a noob with jest, reactjs, and web development, but would love to learn how to conquer this problem. Some resources I have looked at so far are: Unresolved Shopify Mock of FileReader, How to mock a new function in jest, and Mocking FileReader with jasmine.
Any help would be greatly appreciated! Thank you in advance.
2
Answers
Quite possibly the OP has found an answer by now, but since I was facing pretty much the same problem, here’s how I did it – taking input from another SO answer.
I think @Jackyef comment is the right way to go, but I don’t think the call to
mockImplementation
you propose is correct.In my case, the following turned out to be correct.
Worth noting that VSCode highlights a potential refactoring at the anonymous function. It suggests:
I’m still relatively new to JS, so I’m afraid I can’t explain what this is about, nor what refactoring should be done.
I personally could not get any of the jest.spyOn() approaches to work.
Using
jest.spyOn(FileReader.prototype, 'readAsDataURL')
kept generating aCannot spy the readAsDataURL property because it is not a function; undefined given instead
error,and
jest.spyOn(global, "FileReader").mockImplementation(...)
returned aCannot spy the FileReader property because it is not a function; undefined given instead
errorI managed to successfully mock the FileReader prototype using the following:
Then in my test, I was able to test the file input onChange method (which was making use of the FileReader) by mocking the event and triggering it manually like this:
I hope it can help anyone else looking into this.