Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
443 views
in Technique[技术] by (71.8m points)

javascript - 测试自定义钩子使用时,安装程??序函数返回未定义(setup function returns undefined when testing a custom hook usePrevious)

I have got code for usePrevious hook from somewhere on internet.

(我已经从互联网上的某个地方获取了useUsePrevious的代码。)

The code for usePrevious looks like:

(usePrevious的代码如下:)

export const usePrevious = (value) => {
  const ref = useRef();
  useEffect(() => {
    ref.current = value;
  }, [value]);
  return ref.current;
};

Now, I am learing testing react with jest and enzyme.

(现在,我正在测试与玩笑和酵素的反应。)

So, I tried to test usePrevious and got some problems.

(因此,我尝试测试usePrevious并遇到了一些问题。)

Here is my test case:

(这是我的测试用例:)

import React from 'react';
import { render } from 'enzyme';

import { usePrevious } from './customHooks';

const Component = ({ children, value }) => children(usePrevious(value));
const setup = (value) => {
  let returnVal = '';
  render(
    <Component value={value}>
      {
        (val) => {
          returnVal = val;
          return null;
        }
      }
    </Component>,
  );
  return returnVal;
};

describe('usePrevious', () => {
  it('returns something', () => {
    const test1 = setup('test');
    const test2 = setup(test1);
    expect(test2).toBe('test');
  });
});

When the test execution completes, I get this error:

(测试执行完成后,出现以下错误:)

Expected: 'test', Received: undefined

Can anyone please let me know why am I getting undefined and is this the correct way to test custom hoooks in react?

(谁能让我知道为什么我变得未定义,这是测试react挂钩的正确方法吗?)

After suggestion from comments from @Dmitrii G, I have changed my code to re-render the component (Previously I was re-mounting the component).

(在@Dmitrii G的注释中提出建议后,我更改了代码以重新渲染组件(以前我是在重新安装组件)。)

Here is the updated code:

(这是更新的代码:)

import React from 'react';
import PropTypes from 'prop-types';
import { shallow } from 'enzyme';

import { usePrevious } from './customHooks';

const Component = ({ value }) => {
  const hookResult = usePrevious(value);
  return (
    <div>
      <span>{hookResult}</span>
      <span>{value}</span>
    </div>
  );
};

Component.propTypes = {
  value: PropTypes.string,
};

Component.defaultProps = {
  value: '',
};


describe('usePrevious', () => {
  it('returns something', () => {
    const wrapper = shallow(<Component value="test" />);
    console.log('>>>>> first time', wrapper.find('div').childAt(1).text());
    expect(wrapper.find('div').childAt(0).text()).toBe('');

    // Test second render and effect
    wrapper.setProps({ value: 'test2' });
    console.log('>>>>> second time', wrapper.find('div').childAt(1).text());
    expect(wrapper.find('div').childAt(0).text()).toBe('test');
  });
});

But still I am getting the same error

(但是我仍然遇到相同的错误)

Expected: "test", Received: ""

Tests Passes when settimeout is introduced:

(引入settimeout时测试通过:)

import React from 'react';
import PropTypes from 'prop-types';
import { shallow } from 'enzyme';

import { usePrevious } from './customHooks';

const Component = ({ value }) => {
  const hookResult = usePrevious(value);
  return <span>{hookResult}</span>;
};

Component.propTypes = {
  value: PropTypes.string,
};

Component.defaultProps = {
  value: '',
};


describe('usePrevious', () => {
  it('returns empty string when component is rendered first time', () => {
    const wrapper = shallow(<Component value="test" />);
    setTimeout(() => {
      expect(wrapper.find('span').text()).toBe('');
    }, 0);
  });
  it('returns previous value when component is re-rendered', () => {
    const wrapper = shallow(<Component value="test" />);
    wrapper.setProps({ value: 'test2' });
    setTimeout(() => {
      expect(wrapper.find('span').text()).toBe('test');
    }, 0);
  });
});

I am not a big fan of using settimeout, so I feel that probably i am doing some mistake.

(我不是使用settimeout的忠实拥护者,所以我觉得我可能在做一些错误。)

If anyone knows a solution that does not use settimeout, feel free to post here.

(如果有人知道不使用settimeout的解决方案,请随时在此处发布。)

Thank you.

(谢谢。)

  ask by Vishal translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Enzyme by the hood utilizes React's shallow renderer.

(引擎盖上的酶利用了React的浅层渲染器。)

And it has issue with running effects .

(并且它具有运行效果问题 。)

Not sure if it's going to be fixed soon.

(不知道它是否会很快修复。)

Workaround with setTimeout was a surprise to me, did not know it works.

(setTimeout解决方法令我感到惊讶,不知道它能起作用。)

Unfortunately, it is not universal approach since you'd need to use that on any change that cases re-render.

(不幸的是,这不是通用方法,因为您需要在案例重新呈现的任何更改中使用该方法。)

Really fragile.

(真脆弱。)

As a solution you can use mount() instead.

(作为解决方案,您可以改用mount() 。)

Also you may mimic shallow rendering with mount() with mocking every nested component:

(另外,您可以通过模拟每个嵌套组件来使用mount()模仿浅渲染:)

jest.mock("../MySomeComponent.jsx", () =>
  (props) => <span {...props}></span>
);

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...