我正在测试如下所示的自定义 React Hook。它的功能是获取图像的大小,然后使用提供的道具来计算用户想要的图像大小。
import { useEffect, useState } from 'react';
import { Image, LayoutAnimation, useWindowDimensions } from 'react-native';
export type SizeType =
| {
width: number;
height: number;
}
| undefined;
export const useImageSize = (imageUri: string, fillWidth?: boolean, fillHeight?: boolean, width?: number, height?: number): SizeType => {
const [size, setSize] = useState<SizeType>();
const { width: screenWidth, height: screenHeight } = useWindowDimensions();
useEffect(() => {
Image.getSize(
imageUri,
(w, h) => {
LayoutAnimation.easeInEaseOut();
if (fillWidth) {
setSize({
width: screenWidth,
height: h * (screenWidth / w),
});
return;
}
if (fillHeight) {
setSize({
height: screenHeight,
width: w * (screenHeight / h),
});
return;
}
if (width && !height) {
setSize({
width,
height: h * (width / w),
});
return;
}
if (!width && height) {
setSize({
width: w * (height / h),
height: height,
});
}
},
() => {
setSize({ width: 0, height: 0 });
}
);
}, [imageUri, fillWidth, fillHeight, screenWidth, screenHeight, width, height]);
console.log('size', size);
return size;
};
这是这个钩子的测试。它模拟了 Image 组件的 getSize 方法,还模拟了 React Native 的 useWindowDimension 钩子。
import * as RN from 'react-native';
import { renderHook, act } from '@testing-library/react-hooks';
import { useImageSize } from '@app/hooks/useImageSize';
describe('useImageSize', () => {
const getSizeSpyOn = jest.spyOn(RN.Image, 'getSize').mockImplementation(jest.fn());
afterEach(() => {
jest.clearAllMocks();
});
it('should return the correct size when we want to fill the width of the screen', () => {
jest.spyOn(RN, 'useWindowDimensions').mockReturnValue({ width: 200, height: 200, fontScale: 1, scale: 1 });
const { result } = renderHook(() => {
useImageSize('test_image', true, false)
});
expect(getSizeSpyOn).toHaveBeenCalledTimes(1)
const getSizeArgs = getSizeSpyOn.mock.calls[0]!;
expect(getSizeArgs[0]).toBe('test_image');
const success = getSizeArgs[1];
void act(() => {
success(100, 50);
});
console.log('result.current', result.current)
expect(result.current).toEqual({
width: 200,
height: 100,
});
});
console.log('result.current', result.current)
expect(result.current).toEqual({
width: 200,
height: 100,
});
});
});
运行测试后,钩子中的控制台日志从 undefined 变为 { width: 200, height: 100 } 这是预期值,但是,测试中的控制台日志仍然未定义。我认为这种行为表明在测试期间,钩子的行为符合预期,只是由于某种原因,测试中钩子的当前值在新值可用后没有更新。
有谁知道如何解决这个问题?