首页 > 解决方案 > 如何在 redux 工具包中模拟 store

问题描述

import React from 'react';
import { Provider } from 'react-redux';
import configureStore from 'redux-mock-store';
import { render, screen, fireEvent } from '@testing-library/react';
import MyApp from './MyApp ';

const initialState = {};
const mockStore = configureStore(initialState);

describe('<MyApp />', () => {
  it('click button and shows modal', () => {
    render(
      <Provider store={mockStore}>
        <MyApp />
      </Provider>
    );

    fireEvent.click(screen.getByText('ADD MIOU'));
    expect(queryByText('Add MIOU Setting')).toBeInTheDocument();
  });
});

我正在使用 jest 和 redux 工具包reactjs,并尝试模拟商店来编写测试。但是出现以下错误

TypeError:store.getState 不是函数

有没有什么办法解决这一问题?我错过了什么吗?

标签: reactjsreduxreact-testing-library

解决方案


我假设您正在尝试测试一个连接的组件,并且您希望 (1) 运行动作创建者和缩减程序以及 (2) 作为测试的一部分更新 redux 状态?

我没有使用过 redux-mock-store,但我在他们的文档中看到了以下注释,这让我相信这个库可能无法按您期望的方式工作:

请注意,此库旨在测试与动作相关的逻辑,而不是与减速器相关的逻辑。换句话说,它不会更新 Redux 存储。

我建议您尝试这种方法来测试连接的组件。我已经使用这种方法来编写更新 redux 状态和渲染连接组件的测试。

首先,覆盖 RTLrender方法:

// test-utils.js
import React from 'react'
import { render as rtlRender } from '@testing-library/react'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
// Import your own reducer
import reducer from '../reducer'

function render(
  ui,
  {
    initialState,
    store = createStore(reducer, initialState),
    ...renderOptions
  } = {}
) {
  function Wrapper({ children }) {
    return <Provider store={store}>{children}</Provider>
  }
  return rtlRender(ui, { wrapper: Wrapper, ...renderOptions })
}

// re-export everything
export * from '@testing-library/react'
// override render method
export { render }

然后你直接引用新的渲染方法而不是 RTL。您还可以为您的测试提供初始状态。

import React from 'react'
// We're using our own custom render function and not RTL's render
// our custom utils also re-export everything from RTL
// so we can import fireEvent and screen here as well
import { render, fireEvent, screen } from '../../test-utils'
import App from '../../containers/App'

it('Renders the connected app with initialState', () => {
  render(<App />, { initialState: { user: 'Redux User' } })

  expect(screen.getByText(/redux user/i)).toBeInTheDocument()
})

(所有代码均从redux.js.org复制。)


推荐阅读