使用 Jest、RTL、Redux Toolkit、React 进行测试时模拟 useAppSelector 的问题
2023-12-03
219
我已安装 react redux 工具包,并添加了 jest 而不是 vitest 进行测试。
我想测试模式窗口是否在 App 组件中呈现(如果 isOpen 标志为 true)。我只模拟了我需要的商店部分。不是整个商店。
应用组件
function App() {
const { isOpen: isPostModalWindowOpen } = useAppSelector(selectPostModal)
return (
<div className="app-container" id="app-container">
{isPostModalWindowOpen && <PostModalWindow />}
<Posts />
<PageLoader />
<Alert />
</div>
)
}
export default App
测试文件
import App from "../App"
import { PostModalWindow } from "../components/PostModalWindow/PostModalWindow"
import { selectPostModal } from "../redux/postModal"
import { Alert } from "../components/Alert/Alert"
import { PageLoader } from "../components/PageLoader/PageLoader"
import { Posts } from "../components/Posts/Posts"
import { useAppSelector } from "../redux/hooks"
import { render } from "@testing-library/react"
import { RootState } from "../redux/store"
import { clone } from "ramda"
jest.mock("../App", () => ({
...jest.requireActual("../App"),
App: jest.fn(),
}))
jest.mock("../components/PostModalWindow/PostModalWindow", () => ({
...jest.requireActual("../components/PostModalWindow/PostModalWindow"),
PostModalWindow: jest.fn(),
}))
jest.mock("../redux/hooks", () => ({
...jest.requireActual("../redux/hooks"),
useAppSelector: jest.fn(),
}))
jest.mock("../redux/postModal", () => ({
...jest.requireActual("../redux/postModal"),
selectPostModal: jest.fn(),
}))
jest.mock("../components/Alert/Alert", () => ({
...jest.requireActual("../components/Alert/Alert"),
Alert: jest.fn(),
}))
jest.mock("../components/PageLoader/PageLoader", () => ({
...jest.requireActual("../components/PageLoader/PageLoader"),
PageLoader: jest.fn(),
}))
jest.mock("../components/Posts/Posts", () => ({
...jest.requireActual("../components/Posts/Posts"),
Posts: jest.fn(),
}))
describe("Test <App />", () => {
beforeEach(() => {
jest.clearAllMocks()
const initialState = {
postModal: {
isOpen: true,
},
} as RootState
let currentState: RootState
currentState = clone(initialState)
jest.mocked(useAppSelector).mockImplementation((fn) => fn(currentState))
})
it("show modal window if isOpen is true", () => {
const { container } = render(<App />)
expect(container).toMatchSnapshot()
})
})
如何修复此测试错误: TypeError:无法解构'(0 , hooks_1.useAppSelector)(...)'的属性'isOpen',因为它未定义。
我在
jest.mocked(useAppSelector).mockImplementation((fn) => fn(currentState))
中console.logged当前状态,它返回
postModal: {isOpen: true>
,所以我不知道为什么它说它未定义。
1个回答
我通过意识到测试方法中的两个错误解决了这个问题。
首先,我错误地尝试模拟 App 组件。由于我们正在测试 App 组件本身,因此无需模拟它。模拟它会干扰实际的测试过程。
其次,我错误地处理了 selectPostModal 的模拟。我没有提供值,而是尝试创建一个模拟。
import App from "../App"
import { PostModalWindow } from "../components/PostModalWindow/PostModalWindow"
import { useAppSelector } from "../redux/hooks"
import { Alert } from "../components/Alert/Alert"
import { PageLoader } from "../components/PageLoader/PageLoader"
import { Posts } from "../components/Posts/Posts"
import { render } from "@testing-library/react"
import { RootState } from "../redux/store"
import { clone } from "ramda"
jest.mock("../components/PostModalWindow/PostModalWindow", () => ({
...jest.requireActual("../components/PostModalWindow/PostModalWindow"),
PostModalWindow: jest.fn(),
}))
jest.mock("../redux/hooks", () => ({
...jest.requireActual("../redux/hooks"),
useAppSelector: jest.fn(),
}))
jest.mock("../components/Alert/Alert", () => ({
...jest.requireActual("../components/Alert/Alert"),
Alert: jest.fn(),
}))
jest.mock("../components/PageLoader/PageLoader", () => ({
...jest.requireActual("../components/PageLoader/PageLoader"),
PageLoader: jest.fn(),
}))
jest.mock("../components/Posts/Posts", () => ({
...jest.requireActual("../components/Posts/Posts"),
Posts: jest.fn(),
}))
describe("Test <App />", () => {
const initialState = {
postModal: {
isOpen: true,
},
} as RootState
let currentState: RootState
beforeEach(() => {
jest.clearAllMocks()
currentState = clone(initialState)
jest.mocked(useAppSelector).mockImplementation((fn) => fn(currentState))
jest
.mocked(PostModalWindow)
.mockImplementation(() => <div>mockedPostModalWindow</div>)
jest.mocked(Posts).mockImplementation(() => <div>mockedPosts</div>)
jest
.mocked(PageLoader)
.mockImplementation(() => <div>mockedPageLoader</div>)
jest.mocked(Alert).mockImplementation(() => <div>mockedAlert</div>)
})
it("show modal window if isOpen is true", () => {
const { container } = render(<App />)
expect(container).toMatchSnapshot()
})
it("Don't show modal window if isOpen is false", () => {
currentState.postModal.isOpen = false
const { container } = render(<App />)
expect(container).toMatchSnapshot()
})
})
George Tsintsadze
2023-12-04