簡體   English   中英

如何使用模擬更改來測試 FileReader onload?

[英]How to test FileReader onload using simulate change in jest?

簡單對話.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>
);

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();
});

運行測試時,它給了我錯誤TypeError: Illegal invocation

誰能幫我完成這個單元測試? 我只想模擬圖像的src是否有價值。

錯誤的原因是onload被定義為屬性描述符,並且不支持將其分配給由spyOn完成的FileReader.prototype

沒有理由模擬onload ,因為它是在測試代碼中分配的並且需要測試。

直接的方法是不修補 JSDOM FileReader實現,而是完全存根:

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');

檢查應該在 FileReader.onload 上調用的一些副作用時遇到了同樣的問題,所以我只是在觸發事件后設置了一個短暫的暫停(我正在使用酶 + 玩笑)。 設置超時可能不是這里最好的解決方案,但它是唯一有效的方法。

const pauseFor = milliseconds => new Promise(resolve => setTimeout(resolve, milliseconds));
...
wrapper.find('.upload-box').simulate('drop', someMockedDropEvent);
// set pause was the only way to make reader.onload to fire
await pauseFor(100);
expect(something).toEqual(something)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM