首页 > 解决方案 > 无法使用 redux 在 react-testing-utils 中进行基本测试

问题描述

我无法使用 react-test-utils 和 Redux 进行基本测试,如下所示。

import React from 'react'
import { Provider } from 'react-redux'
import { combineReducers } from 'redux'
import { configureStore } from '@reduxjs/toolkit'
import { render } from '@testing-library/react'

it('renders welcome message', () => {
    const store = configureStore({
        reducer: combineReducers({}),
    })

    console.log(store)

    const { getByText } = render(
        <Provider store={store}>
            <h1>hi</h1>
        </Provider>
    )
    expect(getByText('hi')).toBeInTheDocument()
})

它失败并出现此错误

    Provider(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.

      14 |      console.log(store)
      15 | 
    > 16 |      const { getByText } = render(
         |                            ^
      17 |              <Provider store={store}>
      18 |                      <h1>hi</h1>
      19 |              </Provider>

      at reconcileChildFibers (node_modules/react-dom/cjs/react-dom.development.js:14348:23)
      at reconcileChildren (node_modules/react-dom/cjs/react-dom.development.js:16762:28)
      at mountIndeterminateComponent (node_modules/react-dom/cjs/react-dom.development.js:17542:5)
      at beginWork (node_modules/react-dom/cjs/react-dom.development.js:18596:16)
      at HTMLUnknownElement.callCallback (node_modules/react-dom/cjs/react-dom.development.js:188:14)
...

但是,如果注释掉<Provider>如下所示的内容,则测试通过

it('renders welcome message', () => {
    const store = configureStore({
        reducer: combineReducers({}),
    })

    console.log(store)

    const { getByText } = render(
        // <Provider store={store}>
            <h1>hi</h1>
        // </Provider>
    )
    expect(getByText('hi')).toBeInTheDocument()
})

标签: reactjsreduxreact-testing-library

解决方案


您可以将 Provider 指定为包装器以从 react-testing 库中呈现方法

it('renders welcome message', () => {
    const store = configureStore({
        reducer: combineReducers({}),
    })

    console.log(store)
    const Wrapper = ({children}) => {
         return <Provider store={store}>{children}</Provider>
    }
    const { getByText } = render(
         <h1>hi</h1>, 
         {wrapper: Wrapper}
    )
    expect(getByText('hi')).toBeInTheDocument()
})

您还可以覆盖测试库的渲染方法以使包装器逻辑通用,如文档中所述

// 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 { initialState as reducerInitialState, reducer } from './reducer'

function render(
  ui,
  {
    initialState = reducerInitialState,
    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 }

并像使用它一样

// counter.test.js
import React from 'react'
import { createStore } from 'redux'
// 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 '@testing-library/jest-dom/extend-expect'

it('renders welcome message', () => {
    const store = configureStore({
        reducer: combineReducers({}),
    })

    const { getByText } = render(
            <h1>hi</h1>,
         {store}
    )
    expect(getByText('hi')).toBeInTheDocument()
})

推荐阅读