模拟 React useRef 或带有酶和玩笑的功能组件内的函数? [英] Mock React useRef or a function inside a functional component with enzyme and jest?

查看:25
本文介绍了模拟 React useRef 或带有酶和玩笑的功能组件内的函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Codesanbox link - 包括工作组件 Child2.js 和工作测试 Child2.test.js

Child2.js

import React, { useRef } from "react";导出默认函数 Child2() {常量 divRef = useRef();函数 getDivWidth() {如果(divRef.current){console.log(divRef.current);}返回 divRef.current ?divRef.current.offsetWidth : "";}函数 getDivText() {常量 divWidth = getDivWidth();如果(divWidth){if (divWidth > 100) {返回ABC";}返回123";}返回123";}返回 (<><div id="myDiv" ref={divRef}>{getDivText()}</div><p>Div 宽度为:{getDivWidth()}</p></>);}

Child2.test.js

从react"导入反应;进口酶,{浅}从酶";从enzyme-adapter-react-16"导入适配器;从../src/Child2"导入 Child2;Enzyme.configure({ 适配器:新适配器() });it("当 div 宽度大于 100 时,div 文本为 ABC", () => {const wrapper = shallow(<Child2/>);期望(wrapper.find(#myDiv").exists()).toBe(真);期望(wrapper.find("#myDiv").text()).toBe("ABC");});it("当 div 宽度小于 100 时,div 文本为 123", () => {const wrapper = shallow(<Child2/>);期望(wrapper.find(#myDiv").exists()).toBe(真);期望(wrapper.find("#myDiv").text()).toBe("123");});

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

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

解决方案

你可以使用 jest.mock(moduleName, factory, options)jest.requireActual(moduleName) APIs 来模拟 useRef 钩子,除了其他的.这意味着 react 的其他函数和方法仍然是原始版本.

例如

index.jsx:

import React, { useRef } from 'react';导出默认函数 Child2() {常量 divRef = useRef();函数 getDivWidth() {如果(divRef.current){console.log(divRef.current);}返回 divRef.current ?divRef.current.offsetWidth : '';}函数 getDivText() {常量 divWidth = getDivWidth();如果(divWidth){if (divWidth > 100) {返回'ABC';}返回123";}返回123";}返回 (<>

index.test.jsx:

import React, { useRef } from 'react';从酶"导入{浅};从./"导入 Child2;jest.mock('react', () => {const originReact = jest.requireActual('react');常量 mUseRef = jest.fn();返回 {...起源反应,使用参考:mUseRef,};});描述('61782695', () => {it('应该通过', () => {const mRef = { current: { offsetWidth: 100 } };useRef.mockReturnValueOnce(mRef);const wrapper = shallow(<Child2></Child2>);期望(wrapper.find('#myDiv').text()).toBe('123');expect(wrapper.find('p').text()).toBe('Div width is: 100');});it('应该通过 - 2', () => {const mRef = { current: { offsetWidth: 300 } };useRef.mockReturnValueOnce(mRef);const wrapper = shallow(<Child2></Child2>);期望(wrapper.find('#myDiv').text()).toBe('ABC');expect(wrapper.find('p').text()).toBe('Div width is: 300');});it('应该通过 - 3', () => {常量 mRef = {};useRef.mockReturnValueOnce(mRef);const wrapper = shallow(<Child2></Child2>);期望(wrapper.find('#myDiv').text()).toBe('123');expect(wrapper.find('p').text()).toBe('Div 宽度为:');});});

100% 覆盖率的单元测试结果:

 PASS stackoverflow/61782695/index.test.jsx (9.755s)61782695✓ 应该通过(111ms)✓ 应该通过 - 2 (15ms)✓ 应该通过 - 3 (1ms)控制台日志{ 偏移宽度:100 }在 getDivWidth (stackoverflow/61782695/index.jsx:8:15)控制台日志{ 偏移宽度:100 }在 getDivWidth (stackoverflow/61782695/index.jsx:8:15)控制台日志{ 偏移宽度:300 }在 getDivWidth (stackoverflow/61782695/index.jsx:8:15)控制台日志{ 偏移宽度:300 }在 getDivWidth (stackoverflow/61782695/index.jsx:8:15)------------|---------|----------|---------|----------|--------------------文件 |% 语句 |% 分支 |% 功能 |% 行 |未覆盖线#s------------|---------|----------|---------|----------|--------------------所有文件 |100 |100 |100 |100 |index.jsx |100 |100 |100 |100 |------------|---------|----------|---------|----------|--------------------测试套件:1 个通过,共 1 个测试:3 次通过,共 3 次快照:共 0 个时间:10.885s

软件包版本:

"react":"^16.13.1",react-dom":^16.13.1",酶":^3.11.0",酶适配器反应 16":^1.15.2",开玩笑":^25.5.4",开玩笑环境酶":^7.1.2",开玩笑酶":^7.1.2",

Codesanbox link - includes working component Child2.js and working test 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");
});

When i run the tests, obvisouly the offsetWidth of the div is 0, hence i need to find a way to mock the useRef to return a div element with width or mock the getDivWidth function to return a desired number for the width.

How could I achieve that? I have searched for a solution, but I am stuck. There are some examples with class components or using typescript which I have not managed to use.

解决方案

You can use jest.mock(moduleName, factory, options) and jest.requireActual(moduleName) APIs to mock useRef hook except others. Which means other functions and methods of react are still original version.

E.g.

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: ');
  });
});

Unit test results with 100% coverage:

 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

package versions:

"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",

这篇关于模拟 React useRef 或带有酶和玩笑的功能组件内的函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆