当我使用 useSelector 时,React 测试库无法工作
React Testing Library cannot work when I use useSelector
我有一个带有 Redux useSelector
的组件,当我想测试渲染文本时,它在 useSelector
上显示错误消息,并显示错误消息:could not find react-redux context value; please ensure the component is wrapped in a <Provider>
。我已经把 <Provider>
放到了顶层组件,我的测试代码哪里出错了?该应用程序本身 运行 正确。
顶级组件:
import React from "react"
import ReactDOM from "react-dom"
import App from "./App"
import { Provider } from "react-redux"
import store from "./redux/store"
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("test")
)
App.js
import { useEffect, useState, useCallback } from "react"
import { useDispatch, useSelector } from "react-redux"
import { fetchPosts, showName } from "./redux/actions/posts"
import Main from "./component/main"
function App() {
const { posts, name } = useSelector((state) => state.posts)
const dispatch = useDispatch()
const handleClick = useCallback(() => {
dispatch(fetchPosts())
}, [])
const handleShowName = useCallback((textName) => {
dispatch(showName(textName))
}, [])
return (
<div className="App" data-test="appComponent">
<button onClick={handleClick}>get post</button>
<button onClick={() => handleShowName("test")}>Show name</button>
<section className="main">
<div>project name: {name}</div>
<Main posts={posts} />
</section>
</div>
)
}
export default App
app.test.js
import React from "react"
import App from "./App"
import { render, fireEvent, screen } from "@testing-library/react"
it("render a div with text 'project name'", () => {
const { container, getByText } = render(<App />)
expect(getByText("project name:")).toBeInTheDocument()
})
当我测试我的 redux action 和 redux reducer 时,我的测试工作正常。所以 Jest
设置应该没问题。
jest.config.js
module.exports = {
setupFilesAfterEnv: ["./setupTests.js"]
}
setupTest.js
import '@testing-library/jest-dom/extend-expect';
babel.config.js
module.exports = {
presets: ["@babel/preset-env", "@babel/preset-react"],
plugins: [
["@babel/plugin-proposal-class-properties", { loose: false }],
[
"@babel/plugin-transform-runtime",
{
corejs: 3,
helpers: true,
regenerator: true
}
]
]
}
您需要为被测试的组件提供 redux 上下文(隔离)。
最低限度是创建一个简单的 wrapper component (see also custom render),类似于应用程序中的提供程序,传入 render
测试实用程序的选项。
import { Provider } from "react-redux"
import store from "./redux/store"
const ReduxWrapper = ({ children }) => (
<Provider store={store}>
{children}
</Provider>
);
it("render a div with text 'project name'", () => {
const { container, getByText } = render(
<App />,
{ wrapper: ReduxWrapper },
);
expect(getByText("project name:")).toBeInTheDocument()
});
查看 Redux 文档进行测试 connected components。
要点是创建一个包含您的 redux 存储的自定义呈现函数。
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 store from "./redux/store";
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 };
然后为了测试您导入自定义 render
实用程序
import { render, fireEvent, screen } from "../testUtils";
it("render a div with text 'project name'", () => {
const { container, getByText } = render(
<App />,
// pass any options here like initial state, custom store, etc...
);
expect(getByText("project name:")).toBeInTheDocument();
});
我有一个带有 Redux useSelector
的组件,当我想测试渲染文本时,它在 useSelector
上显示错误消息,并显示错误消息:could not find react-redux context value; please ensure the component is wrapped in a <Provider>
。我已经把 <Provider>
放到了顶层组件,我的测试代码哪里出错了?该应用程序本身 运行 正确。
顶级组件:
import React from "react"
import ReactDOM from "react-dom"
import App from "./App"
import { Provider } from "react-redux"
import store from "./redux/store"
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("test")
)
App.js
import { useEffect, useState, useCallback } from "react"
import { useDispatch, useSelector } from "react-redux"
import { fetchPosts, showName } from "./redux/actions/posts"
import Main from "./component/main"
function App() {
const { posts, name } = useSelector((state) => state.posts)
const dispatch = useDispatch()
const handleClick = useCallback(() => {
dispatch(fetchPosts())
}, [])
const handleShowName = useCallback((textName) => {
dispatch(showName(textName))
}, [])
return (
<div className="App" data-test="appComponent">
<button onClick={handleClick}>get post</button>
<button onClick={() => handleShowName("test")}>Show name</button>
<section className="main">
<div>project name: {name}</div>
<Main posts={posts} />
</section>
</div>
)
}
export default App
app.test.js
import React from "react"
import App from "./App"
import { render, fireEvent, screen } from "@testing-library/react"
it("render a div with text 'project name'", () => {
const { container, getByText } = render(<App />)
expect(getByText("project name:")).toBeInTheDocument()
})
当我测试我的 redux action 和 redux reducer 时,我的测试工作正常。所以 Jest
设置应该没问题。
jest.config.js
module.exports = {
setupFilesAfterEnv: ["./setupTests.js"]
}
setupTest.js
import '@testing-library/jest-dom/extend-expect';
babel.config.js
module.exports = {
presets: ["@babel/preset-env", "@babel/preset-react"],
plugins: [
["@babel/plugin-proposal-class-properties", { loose: false }],
[
"@babel/plugin-transform-runtime",
{
corejs: 3,
helpers: true,
regenerator: true
}
]
]
}
您需要为被测试的组件提供 redux 上下文(隔离)。
最低限度是创建一个简单的 wrapper component (see also custom render),类似于应用程序中的提供程序,传入 render
测试实用程序的选项。
import { Provider } from "react-redux"
import store from "./redux/store"
const ReduxWrapper = ({ children }) => (
<Provider store={store}>
{children}
</Provider>
);
it("render a div with text 'project name'", () => {
const { container, getByText } = render(
<App />,
{ wrapper: ReduxWrapper },
);
expect(getByText("project name:")).toBeInTheDocument()
});
查看 Redux 文档进行测试 connected components。
要点是创建一个包含您的 redux 存储的自定义呈现函数。
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 store from "./redux/store";
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 };
然后为了测试您导入自定义 render
实用程序
import { render, fireEvent, screen } from "../testUtils";
it("render a div with text 'project name'", () => {
const { container, getByText } = render(
<App />,
// pass any options here like initial state, custom store, etc...
);
expect(getByText("project name:")).toBeInTheDocument();
});