[英]How to mock useRef using jest.mock and react testing library
我有一個測試用例,我需要模擬 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
。
所以這里我們需要模擬ref
。
這里的mock ref
也很特別。 除了對部分 mocking 使用jest.mock()
之外, ref.current
屬性將在組件安裝后由react
分配。 為了攔截此操作,我們需要創建一個具有current
ref.current
屬性的模擬ref
object,使用Object.defineProperty()
方法定義此屬性的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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.