我正在尝试测试自定义挂钩的 onload 函数来加载图像,但是当我运行测试时,它会跳过 onload。
挂钩:
import { useEffect, useState } from "react";
const useImage = (src: string) => {
const [loaded, setLoaded] = useState(false);
useEffect(() => {
const image = new Image();
image.src = src;
image.onload = () => {
return setLoaded(true); //can't test it
};
}, [src]);
return { loaded };
};
export default useImage;
测试:
import {
renderHook,
waitFor,
} from "@testing-library/react";
import useImage from "./useImage";
describe("useImage", () => {
it("Loads a data url into an image element", async () => {
const img = new Image();
img.src = "foo";
const { result } = renderHook(() => useImage("foo"));
await waitFor(() =>
expect(result.current).toStrictEqual({ loaded: true }) // loaded is always false
);
});
});
如何让测试在 useEffect 中运行 onload?我正在使用 Jest 和 Typescript。
首先,你的
useImage
钩子除了加载图像然后设置状态之外没有做任何事情。如果这仅用于演示目的,那很好,否则,您应该研究一下您想要使用该钩子实现的目标。
关于测试,如果您使用
jest
和jsdom
来测试。然后 jsdom
仅在实际加载某些内容时触发加载事件。这意味着使用必须在 src
中使用真实图像并更改一些笑话配置,如下所示:
在
package.json
中,如果您使用jest.config.js,请参阅官方文档以获取等效内容。
"jest": {
"preset": "ts-jest",
"testEnvironment": "jsdom", // we need this line
"transform": {
"node_modules/variables/.+\\.(j|t)sx?$": "ts-jest"
},
"testEnvironmentOptions": {
"resources": "usable" // we need this line
},
"transformIgnorePatterns": [
"node_modules/(?!variables/.*)"
]
},
您还需要安装canvas
npm i canvas
那么你的测试现在就要通过了。但是,如果您发现安装新依赖项并更改默认测试框架的工作方式有点问题,那么您可以模拟 Image 对象实现,就个人而言,我更喜欢这种方式:
const LOAD_FAILURE_SRC = 'LOAD_FAILURE_SRC';
const LOAD_SUCCESS_SRC = 'LOAD_SUCCESS_SRC';
beforeAll(() => {
Object.defineProperty(global.Image.prototype, 'src', {
set(src) {
if (src === LOAD_FAILURE_SRC) {
setTimeout(() => this.onerror(new Error('mocked error')));
} else if (src === LOAD_SUCCESS_SRC) {
setTimeout(() => this.onload());
}
},
});
});