You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TypeScript环境配置React-Testing-Library适配Redux-RTK

问题定位与修复方案

1. 补全testing-utils.ts的TS类型与store结构

你在转TSX时没有给自定义render函数加类型,且要保证测试用的store reducer结构和项目全局store完全一致,否则useAppSelector无法正确读取state:

// testing-utils.ts
import React, { ReactElement } from 'react'
import { render as rtlRender, RenderOptions } from '@testing-library/react'
import { configureStore, PreloadedState } from '@reduxjs/toolkit'
import { Provider } from 'react-redux'
// 导入项目所有reducer,和全局store结构保持完全一致
import alertReducer from '../alertSlice'
// 其他业务reducer也需全部导入
// import userReducer from '../userSlice'
import type { RootState } from '../store' // 导入项目全局store定义的RootState类型

// 自定义render函数参数类型
interface CustomRenderOptions extends Omit<RenderOptions, 'wrapper'> {
  preloadedState?: PreloadedState<RootState>
  store?: ReturnType<typeof configureStore<RootState>>
}

function render(
  ui: ReactElement,
  {
    preloadedState,
    store = configureStore({
      reducer: { 
        alert: alertReducer,
        // 其他reducer按全局结构补全
        // user: userReducer
      },
      preloadedState,
    }),
    ...renderOptions
  }: CustomRenderOptions = {}
) {
  function Wrapper({ children }: { children: React.ReactNode }) {
    return <Provider store={store}>{children}</Provider>
  }
  return rtlRender(ui, { wrapper: Wrapper, ...renderOptions })
}

export * from '@testing-library/react'
export { render }

2. 修正测试用例的错误写法

你原有测试用例存在三个明显错误:未渲染被测组件、未正确初始化userEvent、点击事件未加await:

import { render, screen } from "../../../testing-utils/test-utils";
import userEvent from '@testing-library/user-event'
import SelectMedia from './SelectMedia' // 导入被测组件

test.only("when the user clicks the 'click me' button, a snackbar appears", async () => {
  const user = userEvent.setup() // @testing-library/user-event v14+ 必须先调用setup初始化
  render(<SelectMedia />) // 必须先渲染被测组件

  // 初始状态下alert为空,不存在header文本,原有断言逻辑错误
  expect(screen.queryByText(/header/i)).not.toBeInTheDocument();

  const clickMeButton = screen.getByRole("button", { name: /click me/i });
  await user.click(clickMeButton); // 点击是异步操作,必须加await等待事件执行完成

  expect(
    await screen.findByText(/great job header/i)
  ).toBeInTheDocument();
});

3. 修正alertSlice的初始状态

你渲染出现undefined header,说明alertState初始值不是falsy值(如空对象),导致alertState && alertState.message + " header"的逻辑判断失效,拼接出undefined:

// alertSlice.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit'

interface AlertState {
  type: 'success' | 'error'
  message: string
  display: string
}

// 初始值设为null,而非空对象
const initialState: AlertState | null = null

const alertSlice = createSlice({
  name: 'alert',
  initialState,
  reducers: {
    setAlert: (state, action: PayloadAction<AlertState>) => {
      return action.payload
    },
    clearAlert: () => null
  }
})

export const { setAlert, clearAlert } = alertSlice.actions
export default alertSlice.reducer

4. 校验selector逻辑

确认你的selectAlert选择器是从正确的根state字段取值:

export const selectAlert = (state: RootState) => state.alert

内容的提问来源于stack exchange,提问作者kevin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 16:45:03