用React或Jest模拟React useRef或功能组件内部的功能? [英] Mock React useRef or a function inside a functional component with enzyme and jest?

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

问题描述

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



Child2.js

  import React,{useRef} from react; 

导出默认函数Child2(){
const divRef = useRef();

函数getDivWidth(){
if(divRef.current){
console.log(divRef.current);
}
返回divRef.current吗? divRef.current.offsetWidth:;
}

函数getDivText(){
const divWidth = getDivWidth();

if(divWidth){
if(divWidth> 100){
返回 ABC;
}
返回 123;
}

返回 123;
}

return(
<>
< div id = myDiv ref = {divRef}>
{getDivText() }
< / div>
< p> Div宽度为:{getDivWidth()}< / p>
< />
);
}

Child2.test.js

  import从反应进行反应; 
进口酶,{浅}来自酶;
从 enzyme-adapter-react-16导入适配器;
从 ../src/Child2导入Child2;

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

it(当div宽度大于100时div文本为ABC,()=> {
const wrapper = shallow(< Child2 //>));
Expect(wrapper.find(#myDiv)。exists())。toBe(true);
Expect(wrapper.find(#myDiv)。text())。toBe( ABC) ;
});

it(当div宽度小于100时div文本为123,()=> {
const wrapper = shallow(< Child2 //>));
Expect(wrapper.find(#myDiv)。exists())。toBe(true);
Expect(wrapper.find(#myDiv)。text())。toBe( 123) ;
});

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



我该如何实现?我一直在寻找解决方案,但被困住了。有一些关于类组件或使用打字稿的示例,但我没有使用过。

解决方案

您可以使用 jest.mock(模块名称,工厂,选项) jest.requireActual(moduleName) API来模拟 useRef 钩住其他人。这意味着 react 的其他函数和方法仍是原始版本。



例如



index.test.jsx

  import React,{useRef}从'react'; 

导出默认函数Child2(){
const divRef = useRef();

函数getDivWidth(){
if(divRef.current){
console.log(divRef.current);
}
返回divRef.current吗? divRef.current.offsetWidth:’’;
}

函数getDivText(){
const divWidth = getDivWidth();

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

返回 123;
}

return(
<>
< div id = myDiv ref = {divRef}>
{getDivText() }
< / div>
< p> Div宽度为:{getDivWidth()}< / p>
< />
);
}

index.test.jsx

  import React,{useRef} from'react'; 
从酶导入{浅};
从’./’导入Child2;

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

describe('61782695',()=> {
it('should pass',()=> {
const mRef = {当前:{offsetWidth: 100}};
useRef.mockReturnValueOnce(mRef);
const包装=浅(< 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 = {当前:{offsetWidth:300}};
useRef.mockReturnValueOnce(mRef );
const包装=浅(< 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包装=浅(< Child2>< / Child2> );
Expect(wrapper.find('#myDiv')。text())。toBe('123');
Expect(wrapper.f ind(’p’)。text())。toBe(’Div width is:’);
});
});

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



< pre class = lang-sh prettyprint-override> PASS stackoverflow / 61782695 / index.test.jsx(9.755s)
61782695
✓应该通过(111ms)
✓应该通过-2(15ms)
✓应该通过-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}

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

console.log
{offsetWidth:300}

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

----------- | --------- || ---------- | --------- | ------ --- | -------------------
文件| %stmts | %分支|功能百分比| %行|未发现的行号
----------- || --------- | ---------- | --------- | --------- | -------------------
所有文件| 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,
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,


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.test.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或Jest模拟React useRef或功能组件内部的功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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