reactjs - React 测试库如何断言子属性和 Redux 存储更新?

标签 reactjs redux jestjs enzyme react-testing-library

我刚刚开始探索我的 React 应用程序的单元测试框架。我将我的选择锁定在 @testing-library/react 而不是 Enzyme,因为 React 推荐它并有助于编写更健壮的测试。我还计划使用 Jest 来确保完整性。

但在我可以继续使用 React 测试库 之前,我遇到了几个问题。有人可以帮忙吗?

例如,

  1. 有一个 Editor 组件可以根据用户输入更新 Redux store。
  2. 还有另一个组件 Preview 直接从存储中读取值。
  3. 还有第三个组件 Container,它包含上述两个传递一些 props 的组件。

问题:

  1. 如何测试用户在 Editor 组件中的输入是否真的更新了 store?
  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;

最佳答案

这是我的做法:

如何测试用户在编辑器组件中的输入是否真的更新了存储?

查看您的代码,Editor 不会更新存储,它不会调用 useDispatch。但假设它确实如此,使用 https://github.com/reduxjs/redux-mock-store我会为测试中的组件设置一个模拟商店提供者,然后触发用户输入并检查模拟商店是否已使用正确的有效负载分派(dispatch)了正确的操作:

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(...);
  }
}

除此之外,您应该测试您的 store reducer 和 action creator,以确保该 action 正确地修改了 store。

如何测试 Preview 组件是否可以渲染从 store 读取的值?

同样的原则,用一个模拟商店设置你的测试,用相关值初始化这个商店,然后只测试组件显示商店里的东西:

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 组件是否将 props 正确传递给它的子组件?

在这里,您应该一起测试 Container + Preview + Editor,并找到一些可视化的东西来测试(正如真实用户所感知的那样),包括 Container 传递给其子级的 props。

例如,如果 Preview 显示 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();
   }
 }

总而言之,我的方法是:

  • 单独测试 action 和 reducer(测试非常简单,状态机,只是简单的 Jest 测试)
  • 测试组件是否在正确的用户输入上使用正确的有效负载发送正确的操作
  • 模拟商店为从商店读取数据的组件设置相关用例(初始化商店值)

对于最后 2 项,我使用 https://github.com/reduxjs/redux-mock-store .

关于reactjs - React 测试库如何断言子属性和 Redux 存储更新?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62049939/

相关文章:

node.js - Node JS 中的最佳项目方法

javascript - React - 如何在发送 post 请求之前检查 JWT 是否有效?

redux - 如何将 redux 与 graphql 一起使用

javascript - 让 Jest 在故事书中全局可用

typescript - NestJS测试: decorator is not a function

javascript - 如何避免路线冲突?

javascript - 如何在 async/await 函数中修复 'response.json is not a function'

reactjs - Jest 遇到意外标记,因为试图导入 Jest 无法解析的文件

reactjs - 如何模拟 redux 表单的 getFormValues

javascript - 用 Jest 模拟 NextJS 路由器事件