如何使用 React-Testing-Library 测试 mapDispatchToProps?

Posted

技术标签:

【中文标题】如何使用 React-Testing-Library 测试 mapDispatchToProps?【英文标题】:How can I test the mapDispatchToProps with React-Testing-Library? 【发布时间】:2021-11-30 03:21:45 【问题描述】:

我必须测试以下组件:

import React from 'react';
import  connect  from 'react-redux';

import  open as openModal  from 'redux/actions/ModalActions';
import  MODAL_CONTENT_ADD_TO_ALBUM  from 'constants/ModalNameConstants';

import ContentAddToAlbumModal from 'components/ContentAddToAlbumModal';
import AddSection from 'components/AddSection';

export function AddToAlbumButton(props) 
  const  openUploadModal  = props;

  return (
    <>
      <div>
        <div>
          <AddSection
            onClick=openUploadModal
          />
        </div>
      </div>
      <ContentAddToAlbumModal/>
    </>
  );


function mapDispatchToProps(dispatch, props) 
  return 
    openUploadModal() 
      return dispatch(
        openModal(MODAL_CONTENT_ADD_TO_ALBUM, props.content.get('id'))
      );
    ,
  ;


export default connect(null, mapDispatchToProps)(AddToAlbumButton);

我的测试用例如下:

import React from 'react';
import render from '@testing-library/react';
import AddToAlbumButton from 'components/AddToAlbumButton';

jest.mock('components/ContentAddToAlbumModal', () => 
  return function ContentAddToAlbumModal() 
      return (
      <div>
          ContentAddToAlbumModal
      </div>
      )
  ;
);

jest.mock('components/AddSection', () => 
  return function AddSection(openUploadModal) 
      return (
      <div onClick=openUploadModal>
          AddSection
      </div>
      )
  ;
);


describe('AddToAlbumButton component', () => 

  const props = 
    openUploadModal: jest.fn()
  ;

  it('Should render snapshot of AddToAlbumButton component correctly', () => 
    const asFragment = render(<AddToAlbumButton ...props />);    
    expect(asFragment()).toMatchSnapshot();
  )
);

我也想测试我的 mapDispatchToProps 函数,如何在不公开导出的情况下测试它。我应该如何测试连接的组件?

我在网上寻找建议。我发现的一个方法是通过在 jest 目录的 mocks 文件夹中创建一个文件来模拟“react-redux”模块,代码 sn-p 为:

const mockDispatch = jest.fn(action => action);
module.exports = 
    connect: (mapStateToProps, mapDispatchToProps) => reactComponent => (
        mapStateToProps,
        mapDispatchToProps: (dispatch = mockDispatch, ownProps) => (
            mapDispatchToProps(dispatch, ownProps)
        ),
        [reactComponent.displayName || reactComponent.name || 'reactComponent']: reactComponent,
        mockDispatch,
    ),
    Provider: ( children ) => children,
;

我应该如何将上面的代码 sn-p 与“React 测试库”一起使用。我的测试用例缺少什么?我应该怎么做?

谢谢

【问题讨论】:

【参考方案1】:

您可以使用redux-mock-store 包创建模拟商店。用这个模拟商店用Provider 包装你的组件。

您可以通过调用store.getActions() 获取所有操作。最后,您可以使用任何断言库来测试有效负载。

这种测试方式更接近于集成测试,集成了React组件、connectmapDispatchToProps函数。

index.tsx:

import React from 'react';
import  connect  from 'react-redux';
import  open as openModal  from './actions';
import ContentAddToAlbumModal from './components/ContentAddToAlbumModal';
import AddSection from './components/AddSection';
const MODAL_CONTENT_ADD_TO_ALBUM = 'MODAL_CONTENT_ADD_TO_ALBUM';

export function AddToAlbumButton(props) 
  return (
    <>
      <AddSection onClick=props.openUploadModal />
      <ContentAddToAlbumModal />
    </>
  );


function mapDispatchToProps(dispatch, props) 
  return 
    openUploadModal() 
      return dispatch(openModal(MODAL_CONTENT_ADD_TO_ALBUM, props.content.get('id')));
    ,
  ;


export default connect(null, mapDispatchToProps)(AddToAlbumButton);

components/ContentAddToAlbumModal.tsx:

import React from 'react';

export default function ContentAddToAlbumModal() 
  return <div>real ContentAddToAlbumModal</div>;

components/AddSection.tsx:

import React from 'react';

export default function AddSection( onClick ) 
  return <div onClick=onClick>real AddSection</div>;

actions.ts:

export function open(type, id) 
  return  type, payload:  id  ;

index.test.tsx:

import  render, fireEvent, screen  from '@testing-library/react';
import React from 'react';
import  Provider  from 'react-redux';
import createMockStore from 'redux-mock-store';
import AddToAlbumButton from './';

const mockStore = createMockStore();

jest.mock('./components/ContentAddToAlbumModal', () => 
  return function ContentAddToAlbumModal() 
    return <div>ContentAddToAlbumModal</div>;
  ;
);

jest.mock('./components/AddSection', () => 
  return function AddSection( onClick ) 
    return <div onClick=onClick>AddSection</div>;
  ;
);

describe('AddToAlbumButton', () => 
  test('should pass', () => 
    const store = mockStore();
    const content = 
      get(key) 
        return '123';
      ,
    ;
    render(
      <Provider store=store>
        <AddToAlbumButton content=content />
      </Provider>
    );
    fireEvent.click(screen.getByText(/AddSection/));
    expect(store.getActions()).toEqual([ type: 'MODAL_CONTENT_ADD_TO_ALBUM', payload:  id: '123'  ]);
  );
);

测试结果:

 PASS  examples/69525117/index.test.tsx (8.636 s)
  AddToAlbumButton
    ✓ should pass (35 ms)

------------|---------|----------|---------|---------|-------------------
File        | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
------------|---------|----------|---------|---------|-------------------
All files   |     100 |      100 |     100 |     100 |                   
 actions.ts |     100 |      100 |     100 |     100 |                   
 index.tsx  |     100 |      100 |     100 |     100 |                   
------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        9.788 s, estimated 10 s

【讨论】:

以上是关于如何使用 React-Testing-Library 测试 mapDispatchToProps?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用本机反应创建登录以及如何验证会话

如何在自动布局中使用约束标识符以及如何使用标识符更改约束? [迅速]

如何使用 AngularJS 的 ng-model 创建一个数组以及如何使用 jquery 提交?

如何使用laravel保存所有行数据每个行名或相等

如何使用 Math.Net 连接矩阵。如何使用 Math.Net 调用特定的行或列?

WSARecv 如何使用 lpOverlapped?如何手动发出事件信号?