reactjs - 模拟 React useRef 或带有 enzyme 和 Jest 的功能组件内的函数?

标签 reactjs testing mocking jestjs enzyme

密码箱 link - 包括工作组件 Child2.js 和工作测试 Child2.test.js

Child2.js

import React, { useRef } from "react";

export default function Child2() {
  const divRef = useRef();

  function getDivWidth() {
    if (divRef.current) {
      console.log(divRef.current);
    }
    return divRef.current ? divRef.current.offsetWidth : "";
  }

  function getDivText() {
    const divWidth = getDivWidth();

    if (divWidth) {
      if (divWidth > 100) {
        return "ABC";
      }
      return "123";
    }

    return "123";
  }

  return (
    <>
      <div id="myDiv" ref={divRef}>
        {getDivText()}
      </div>
      <p>Div width is: {getDivWidth()}</p>
    </>
  );
}

Child2.test.js
import React from "react";
import Enzyme, { shallow } from "enzyme";
import Adapter from "enzyme-adapter-react-16";
import Child2 from "../src/Child2";

Enzyme.configure({ adapter: new Adapter() });

it("div text is ABC when div width is more then 100 ", () => {
  const wrapper = shallow(<Child2 />);
  expect(wrapper.find("#myDiv").exists()).toBe(true);
  expect(wrapper.find("#myDiv").text()).toBe("ABC");
});

it("div text is 123 when div width is less then 100 ", () => {
  const wrapper = shallow(<Child2 />);
  expect(wrapper.find("#myDiv").exists()).toBe(true);
  expect(wrapper.find("#myDiv").text()).toBe("123");
});

当我运行测试时,显然 div 的 offsetWidth 为 0,因此我需要找到一种方法来模拟 useRef返回具有宽度的 div 元素或模拟 getDivWidth函数返回所需的宽度数。

我怎么能做到这一点?我一直在寻找解决方案,但我被卡住了。有一些带有类组件或使用我没有设法使用的 typescript 的示例。

最佳答案

您可以使用jest.mock(moduleName, factory, options)jest.requireActual(moduleName)用于模拟的 API useRef钩除别人。这意味着react的其他功能和方法仍然是原始版本。
例如。index.jsx :

import React, { useRef } from 'react';

export default function Child2() {
  const divRef = useRef();

  function getDivWidth() {
    if (divRef.current) {
      console.log(divRef.current);
    }
    return divRef.current ? divRef.current.offsetWidth : '';
  }

  function getDivText() {
    const divWidth = getDivWidth();

    if (divWidth) {
      if (divWidth > 100) {
        return 'ABC';
      }
      return '123';
    }

    return '123';
  }

  return (
    <>
      <div id="myDiv" ref={divRef}>
        {getDivText()}
      </div>
      <p>Div width is: {getDivWidth()}</p>
    </>
  );
}
index.test.jsx :
import React, { useRef } from 'react';
import { shallow } from 'enzyme';
import Child2 from './';

jest.mock('react', () => {
  const originReact = jest.requireActual('react');
  const mUseRef = jest.fn();
  return {
    ...originReact,
    useRef: mUseRef,
  };
});

describe('61782695', () => {
  it('should pass', () => {
    const mRef = { current: { offsetWidth: 100 } };
    useRef.mockReturnValueOnce(mRef);
    const wrapper = shallow(<Child2></Child2>);
    expect(wrapper.find('#myDiv').text()).toBe('123');
    expect(wrapper.find('p').text()).toBe('Div width is: 100');
  });

  it('should pass - 2', () => {
    const mRef = { current: { offsetWidth: 300 } };
    useRef.mockReturnValueOnce(mRef);
    const wrapper = shallow(<Child2></Child2>);
    expect(wrapper.find('#myDiv').text()).toBe('ABC');
    expect(wrapper.find('p').text()).toBe('Div width is: 300');
  });

  it('should pass - 3', () => {
    const mRef = {};
    useRef.mockReturnValueOnce(mRef);
    const wrapper = shallow(<Child2></Child2>);
    expect(wrapper.find('#myDiv').text()).toBe('123');
    expect(wrapper.find('p').text()).toBe('Div width is: ');
  });
});
覆盖率 100% 的单元测试结果:
 PASS  stackoverflow/61782695/index.test.jsx (9.755s)
  61782695
    ✓ should pass (111ms)
    ✓ should pass - 2 (15ms)
    ✓ should pass - 3 (1ms)

  console.log
    { offsetWidth: 100 }

      at getDivWidth (stackoverflow/61782695/index.jsx:8:15)

  console.log
    { offsetWidth: 100 }

      at getDivWidth (stackoverflow/61782695/index.jsx:8:15)

  console.log
    { offsetWidth: 300 }

      at getDivWidth (stackoverflow/61782695/index.jsx:8:15)

  console.log
    { offsetWidth: 300 }

      at getDivWidth (stackoverflow/61782695/index.jsx:8:15)

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |     100 |      100 |     100 |     100 |                   
 index.jsx |     100 |      100 |     100 |     100 |                   
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       3 passed, 3 total
Snapshots:   0 total
Time:        10.885s
包版本:
"react": "^16.13.1",
"react-dom": "^16.13.1",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2",
"jest": "^25.5.4",
"jest-environment-enzyme": "^7.1.2",
"jest-enzyme": "^7.1.2",

关于reactjs - 模拟 React useRef 或带有 enzyme 和 Jest 的功能组件内的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61782695/

相关文章:

javascript - React JS 应用程序在本地主机上运行速度非常慢,但在 Azure 服务器上运行正常

javascript - 不要使用 for 循环交替推送到数组

testing - 在页面模型中将参数传递给 TestCafe Selector

Python 模拟库 : Is there any way to get corresponding return values from magic mock calls?

javascript - React下拉菜单的jss样式

javascript - React Native 嵌入阴影效果

testing - 如何在一次测试失败后立即中断测试?

testing - 测试自动化 - Win32 应用程序 - 白色/UI 自动化 - 对象识别问题

mocking - Nightwatch 模拟 HTTP 请求

PHPUnit测试一个函数被调用了多少次