React Testing库如何断言子道具和Redux存储更新?

问题描述 投票:2回答:1

我刚刚开始为我的React应用程序探索一个单元测试框架。我将选择锁定在@testing-library/react上,而不是React推荐的Enzyme上,这有助于编写更可靠的测试。我还打算使用Jest进行完整性检查。

但是在继续进行React Testing Library之前,我陷入了几个问题。有人可以帮忙吗?

例如,

  1. 有一个Editor组件,可根据用户输入更新Redux存储。
  2. 还有另一个组件Preview,它直接从存储中读取值。
  3. 存在第三部分Container,其中包含上述两个通过一些道具的部分。

问题:

  1. 如何测试用户在Editor组件中输入的内容实际上是否更新商店?
  2. 如何测试Preview组件是否可以呈现从商店读取的值?
  3. 如何测试Container组件是否正确地将props传递给它的子代?

Container.jsx

import React from 'react';
import Editor from './Editor';
import Preview from './Preview';

const Container = ({editorType}) => {
  return (
    <div>
      <Editor type={editorType} />
      <Preview />
    </div>
  );
};
export default Container;

Editor.jsx

import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import {setName} from './actions';

const Editor = ({type}) => {
  const name = useSelector(state => state.name);
  const dispatch = useDispatch();

  return (
    <div>
      <h1>Type: {type}</h1>
      <input value={name} onChange={evt => dispatch(setName(evt.target.value))} />
    </div>
  );
};
export default Editor;

Preview.jsx

import React from 'react';
import { useSelector } from 'react-redux';

const Editor = ({type}) => {
  const name = useSelector(state => state.name);

  return (
    <div>
      <h1>Name: {name}</h1>
    </div>
  );
};
export default Preview;
reactjs redux jestjs enzyme react-testing-library
1个回答
0
投票

这是我的处理方式:

如何测试编辑器组件中的用户输入是否实际更新商店?

查看您的代码,编辑器不会更新存储,它不会调用useDispatch。但是假设这样做,我将使用https://github.com/reduxjs/redux-mock-store为测试中的组件设置一个模拟商店提供程序,然后触发用户输入并检查该模拟商店是否已分派了正确的操作以及正确的有效载荷:

describe('<Editor />', () => {
  let store: MockStoreEnhanced;
  let rtl: RenderResult;

  beforeEach(() => {
    store = mockStore({ /* your store structure */ });

    rtl = render(
      <Provider store={store}>
        <Editor type={...} />
      </Provider>
    );
  });

  test('dispatch action correctly', () => {
    fireEvent.change(rtl.container.querySelector('input'), { target: {value: 'test' } });

    // check actions that were dispatched by change event
    // getActions return an array avec redux actions (type, payload)
    expect(store.getActions()).toEqual(...);
  }
}

此外,您还应该测试商店缩减工具和动作创建者,以确保动作正确地修改了商店。

如何测试预览组件是否可以呈现从商店读取的值?

相同的原理,使用模拟商店设置测试,使用相关值初始化该商店,然后测试组件是否显示商店中的内容:

describe('<Preview />', () => {
  let store: MockStoreEnhanced;
  let rtl: RenderResult;

   beforeEach(() => {
     store = mockStore({ name: 'This is name from store' });

     rtl = render(
       <Provider store={store}>
         <Preview type={...} />
       </Provider>
     );
   });

   test('displays store content correctly', () => {
     expect(rtl.getByText('This is name from store')).toBeTruthy();
   }
 }

如何测试容器组件是否正确地将道具传递给子组件?

在这里,您应该一起测试Container + Preview + Editor,并找到可视化的东西进行测试(就像真实用户会看到的一样),其中涉及Container传递给其子级的道具。

例如,如果预览显示props.type,它来自Container editorType props:

describe('<Container />', () => {
  // mocked store may not be necessary here, depending on your use case
  let store: MockStoreEnhanced;
  let rtl: RenderResult;

   beforeEach(() => {
     store = mockStore({ name: 'This is name from store' });

     rtl = render(
       <Provider store={store}>
         <Container editorType={'toTest'} />
       </Provider>
     );
   });

   test('displays store content correctly', () => {
     // check that 'toTest' exists in DOM because it is rendered by Preview component, a child of Container
     expect(rtl.getByText('toTest')).toBeTruthy();
   }
 }

总结起来,我的方法是:

  • 仅测试动作和Reducer(非常易于测试,状态机,仅是简单的Jest测试)
  • 测试组件在正确的用户输入上以正确的有效负载分配正确的动作
  • 模拟存储为从存储中读取数据的组件设置相关用例(初始存储值)>>
  • 对于最后两个项目,我使用https://github.com/reduxjs/redux-mock-store

© www.soinside.com 2019 - 2024. All rights reserved.