我有一个测试用例,我需要模拟 useRef 以返回模拟当前值。我尝试了 jest.mock,但它返回的是 HTMLDivElement。
代码:
const ref = useRef<HTMLDivElement | null>(null);
测试:
jest.mock('react', () => {
const originReact = jest.requireActual('react');
return {
...originReact,
useRef: jest.fn(),
};
});
React.useRef.mockReturnValue({ current: {offsetWith: 100} });
模拟返回
[ { type: 'return', value: { current: [HTMLDivElement] } } ]
最佳答案
@jonrsharpe的建议是组件测试的一般原则,但是你的问题是特例,涉及DOM的一些属性和方法,比如offsetWidth
和getBoundingClientRect()
方法。 jsdom
运行环境无法返回,浏览器运行环境下渲染引擎返回结果导致offsetWidth
和getBoundingClientRect()<返回的属性值
方法始终为 0
。
所以这里我们需要 mock ref
。
这里的 mock ref
也比较特殊。除了使用 jest.mock()
进行部分模拟之外, ref.current
属性将在组件安装后由 react
分配。为了拦截这个操作,我们需要创建一个带有current
对象属性的模拟ref
对象,使用Object.defineProperty()
方法为这个ref.current
属性定义getter
和setter
,并拦截属性赋值。
jest.spyOn
方法采用 accessType 的可选第三个参数,可以是 'get' 或 'set',这在您想要监视 getter 或 setter 时很有用,分别。
例如
index.tsx
:
import React, { useEffect, useRef } from 'react';
export default function App() {
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
console.log(ref.current?.offsetWidth);
}, [ref]);
return <div ref={ref}>app</div>;
}
index.test.tsx
:
import { render } from '@testing-library/react';
import React, { useRef } from 'react';
import { mocked } from 'ts-jest/utils';
import App from './';
jest.mock('react', () => {
return {
...jest.requireActual<typeof React>('react'),
useRef: jest.fn(),
};
});
const useMockRef = mocked(useRef);
describe('66332902', () => {
afterEach(() => {
jest.clearAllMocks();
});
afterAll(() => {
jest.resetAllMocks();
});
test('should mock ref and offsetWidth', () => {
const ref = { current: {} };
Object.defineProperty(ref, 'current', {
set(_current) {
if (_current) {
jest.spyOn(_current, 'offsetWidth', 'get').mockReturnValueOnce(100);
}
this._current = _current;
},
get() {
return this._current;
},
});
useMockRef.mockReturnValueOnce(ref);
render(<App />);
});
});
测试结果:(查看日志)
PASS examples/66332902/index.test.tsx (9.518 s)
66332902
✓ should mock ref and offsetWidth (39 ms)
console.log
100
at examples/66332902/index.tsx:6:13
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 10.106 s
关于reactjs - 如何使用 jest.mock 模拟 useRef 并 react 测试库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66332902/