首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用useRef模拟jest.mock和反应测试库

如何使用useRef模拟jest.mock和反应测试库
EN

Stack Overflow用户
提问于 2021-02-23 12:13:16
回答 1查看 11.9K关注 0票数 3

我有一个测试用例,为了返回一个模拟当前值,我需要模拟useRef。我尝试了jest.mock,但是它返回一个HTMLDivElement。

代码:

代码语言:javascript
运行
复制
   const ref = useRef<HTMLDivElement | null>(null);

测试:

代码语言:javascript
运行
复制
  jest.mock('react', () => {
     const originReact = jest.requireActual('react');
       return {
          ...originReact,
          useRef: jest.fn(),
       };
  });



  React.useRef.mockReturnValue({ current: {offsetWith: 100} }); 

模拟返回

代码语言:javascript
运行
复制
[ { type: 'return', value: { current: [HTMLDivElement] } } ]
EN

回答 1

Stack Overflow用户

发布于 2021-07-20 03:41:12

@jonrsharpe的建议是组件测试的一般原则,但您的问题是一个特例,涉及DOM的一些属性和方法,如offsetWidthgetBoundingClientRect()方法。jsdom的运行时环境无法返回,而呈现引擎在浏览器运行时环境下返回的结果将导致getBoundingClientRect()方法返回的offsetWidth和属性值始终为0

所以这里我们需要模拟ref

这里的模拟ref也很特殊。除了使用jest.mock()进行部分模拟之外,ref.current属性将在组件挂载后由react分配。为了拦截此操作,我们需要创建一个带有current对象属性的模拟current对象,使用Object.defineProperty()方法为该ref.current属性定义gettersetter,并拦截属性分配。

jest.spyOn方法采用accessType的第三个可选参数,该参数可以是“get”,也可以是“set”,这在您想监视getter或setter时非常有用。

例如。

index.tsx

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
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 />);
  });
});

测试结果:(见日志)

代码语言:javascript
运行
复制
 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
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66332902

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档