如何使用玩笑中的模拟更改来测试 FileReader 加载?

ald*_*n27 4 javascript reactjs jestjs enzyme

简单对话框.jsx

const [imagePreview, setImagePreview] = React.useState(null);

const handleChangeImage = event => {
    let reader = new FileReader();
    let file = event.target.files[0];

    reader.onload = event => {
        console.log(event);

        setImagePreview(event.target.result);
    };

    reader.readAsDataURL(file);
};

return (
    <div>
        <input
            accept="image/*"
            id="contained-button-file"
            multiple
            type="file"
            style={{ display: 'none' }}
            onChange={handleChangeImage}
        />

        <img id="preview" src={imagePreview} />
    </div>
);
Run Code Online (Sandbox Code Playgroud)

SimpleDialog.test.js

it('should change image src', () => {
    const event = {
        target: {
            files: [
                {
                    name: 'image.png',
                    size: 50000,
                    type: 'image/png'
                }
            ]
        }
    };

    let spy = jest
        .spyOn(FileReader.prototype, 'onload')
        .mockImplementation(() => null);

    wrapper.find('input[type="file"]').simulate('change', event);

    expect(spy).toHaveBeenCalled();

    expect(wrapper.find('#preview').prop('src')).not.toBeNull();
});
Run Code Online (Sandbox Code Playgroud)

运行测试时,它给我错误TypeError: Illegal induction

谁能帮我完成这个单元测试?我只想模拟图像的src是否有价值。

Est*_*ask 6

错误的原因是不支持onload将其定义为属性描述符并将其分配给FileReader.prototype完成的对象。spyOn

没有理由进行模拟,onload因为它是在经过测试的代码中分配的并且需要进行测试。

最简单的方法是不修补 JSDOMFileReader实现,而是完全存根它:

jest.spyOn(global, 'FileReader').mockImplementation(function () {
    this.readAsDataURL = jest.fn();
});

wrapper.find('input[type="file"]').simulate('change', event);


let reader = FileReader.mock.instances[0];
expect(reader.readAsDataURL).toHaveBeenCalledWith(...);
expect(reader.onload).toBe(expect.any(Function));

expect(wrapper.find('#preview').prop('src')).toBeNull();

reader.onload({ target: { result: 'foo' } });

expect(wrapper.find('#preview').prop('src')).toBe('foo');
Run Code Online (Sandbox Code Playgroud)