如何在 React 中测试子函数?快照是

Posted

技术标签:

【中文标题】如何在 React 中测试子函数?快照是【英文标题】:How can I test functions as child in React? The snapshot is 【发布时间】:2020-11-29 06:37:48 【问题描述】:

我正在创建一个返回标签和子项的组件,该子项是一个函数,用于评估字段是否具有“输入”或“文本区域”类型并返回它:

export const Field = (
  fieldType,
) => 
  return (
    <>
      <label htmlFor=name> label</label>
      () => 
        switch (fieldType) 
          case 'textarea':
            return (
              <textarea
              />
            );
          default:
            return (
              <input/>
            );
        
      
    </>
  );
;

我喜欢通过创建组件的快照来开始我的测试

describe('Unit testing: <Field /> component', () => 
  test('Should render correctly ', () => 
    const wrapper = shallow(<Field fieldType='textarea' />);

    expect(wrapper).toMatchSnapshot();
  );
);

这是我的快照的结果(我正在使用酶转 json):

exports[`Unit testing for Field component Should render correctly  1`] = `
<Fragment>
  <label
    htmlFor="testField"
  >
     
    Test Label
  </label>
  <Component />
</Fragment>
`;

正如你所看到的,孩子已经被渲染了,这对我来说非常模糊......我想知道我怎样才能准确地测试我的组件是否真的在渲染输入或文本区域......

【问题讨论】:

我的快照显示了一个 ,我想知道我可以做些什么来测试我的 是返回输入还是文本区域! 当您使用shallow 时,您明确表示您对正在测试的组件的任何子组件不感兴趣。请改用mount 测试起来可能很尴尬,因为使用起来也很尴尬。测试的一个好处是它们揭示了测试代码中的问题。为什么它首先具有功能孩子?子函数在 React 中可用,但不能在将提供给渲染器的地方使用。 【参考方案1】:

您在回答问题时提到:

我找到了一个实际上对我有好处的可能解决方案:

但这是一个错误的解决方案。您有一个错误的组件,并且您更改了测试以忽略它。你的组件是这样的:

export const Field = (fieldType,) => 
  return (
    <>
      <label htmlFor=name> label</label>
      () => return <input /> <---- it's just a component defination.
    </>
  );
;

如果你像这样使用它:

<Field />

它只会渲染label,而不是textareainput。 (因为渲染函数内部的函数被认为是一个组件定义,你应该调用它以便从中获取要渲染的元素。)

所以测试是正确的,但你的组件是错误的。将您的组件更改为:

export const Field = (fieldType,) => 
  const input = () => 
    return <input />
  
  return (
    <>
      <label htmlFor=name> label</label>
      input()
    </>
  );
;

渲染输入组件,而不仅仅是定义它。

【讨论】:

使用IIFE调用切换输入或文本区域的函数是否正确?就像 (() => switch(fieldType) ... )() @DaniloPeña 有效,但这是一个不好的做法,因为 react 会在每次渲染上创建一个新函数(但我个人认为没关系,性能提升不是那么大):***.com/questions/41369296/… 所以这就是为什么我把它移到了渲染函数之外。 @DaniloPeña(另请注意,在您的原始问题中,您没有在渲染上放置 IIFE,而是放置了定义。以防万一您没有注意到。)【参考方案2】:

我找到了一个实际上对我有好处的可能解决方案:

const innerWrapper = shallow(wrapper.prop('children')[1]());

这个 innerWrapper 从子级创建一个浅层渲染。 快照显示了我想要的:

exports[`Unit testing for Field component Function as children should render correctly 1`] = `
<textarea
  autoComplete="off"
  id="testField"
  name="testField"
  value=""
/>
`;

我实施的完整测试:

test('Function as children should render correctly', () => 
    const innerWrapper = shallow(wrapper.prop('children')[1]());
    expect(innerWrapper).toMatchSnapshot();
    expect(innerWrapper.find(props.fieldType).exists()).toBe(true);
  );

是的,我已经运行了测试并且它通过了。

【讨论】:

您的组件不工作。并且您修改了测试以忽略它。看我的回答。

以上是关于如何在 React 中测试子函数?快照是的主要内容,如果未能解决你的问题,请参考以下文章

如何从函数调用中渲染 React 子组件?

如何 gitignore 快照文件夹?

React 测试库未在快照中显示输入 onChange 道具

在 react native 中使用 jest 和 Storybook 快照测试时出现问题

如何在 React 应用程序中使用 JEST 测试向 api 发出 axios 请求的异步函数

react-native 如何调用子子组件的方法或者属性