react-testing-library测试Show more按钮点击后标签状态未更新如何解决
问题根因
你遇到的报错由两个核心问题导致:
redux-mock-store本身仅用于监听派发的action、验证动作是否正确触发,不会执行实际的reducer逻辑,所以你调用dispatch之后mockStore的state不会自动更新,组件读取到的currentCount、currentResult还是初始值。- 你在点击按钮后直接同步执行断言,没有等待React内部状态更新(
setPageCount是异步更新)和组件重渲染完成,也会导致断言拿到的是更新前的内容。
解决方案
方案1:使用真实Redux Store(更推荐,符合实际运行场景)
直接用你项目中真实的reducer创建store,而不是用mockStore,这样动作派发后会自动走reducer逻辑更新state,和线上运行逻辑完全一致,测试可信度更高。
import { createStore, combineReducers } from 'redux'; import searchReducer from '你的search reducer路径'; test('Show more button click works successfully', async () => { const rootReducer = combineReducers({ search: searchReducer }); const initialTestState = { search: { ...initialState.search, mainResult: SearchData.test.large, currentResult: SearchData.test.large.slice(0, 15), currentCount: 15, currentTotal: 16, }, }; // 用初始状态创建真实store const store = createStore(rootReducer, initialTestState); const { getByTestId, findByTestId } = render( <Provider store={store}> <SearchListing {...props} /> </Provider> ); const showMoreBtn = getByTestId('search-listing-result-footer-btn'); expect(getByTestId('search-listing-result-footer-label')).toHaveTextContent('Showing 15 of 16 results'); userEvent.click(showMoreBtn); // 等待更新完成后断言,findBy是异步查询,会自动等待元素内容更新 expect(await findByTestId('search-listing-result-footer-label')).toHaveTextContent('Showing 16 of 16 results'); });
方案2:必须使用mockStore的处理方式
如果你的测试场景只需要验证动作派发正确、组件渲染和内部状态逻辑正确,可以手动等待状态更新后,验证派发的动作是否符合预期,再手动更新mockStore的state触发组件重渲染。
test('Show more button click works successfully', async () => { const state = { search: { ...initialState.search, mainResult: SearchData.test.large, currentResult: SearchData.test.large.slice(0, 15), currentCount: 15, currentTotal: 16, }, }; store = mockStore(state); const { getByTestId, rerender } = render( <Provider store={store}> <SearchListing {...props} /> </Provider> ); const showMoreBtn = getByTestId('search-listing-result-footer-btn'); expect(getByTestId('search-listing-result-footer-label')).toHaveTextContent('Showing 15 of 16 results'); userEvent.click(showMoreBtn); // 先验证派发的动作是否正确 const actions = store.getActions(); expect(actions[0].type).toBe('search/showMore'); // 替换成你实际的action type expect(actions[0].payload.currentCount).toBe(16); // 手动更新store的state,重新渲染组件 const newState = { ...state, search: { ...state.search, ...actions[0].payload } }; store = mockStore(newState); rerender( <Provider store={store}> <SearchListing {...props} /> </Provider> ); expect(getByTestId('search-listing-result-footer-label')).toHaveTextContent('Showing 16 of 16 results'); });
额外排查点
如果修改后还是有问题,可以检查这两个细节:
- 确认
pageCount的初始值是否为0,否则点击后newPageCount可能超出resultsChunk的下标范围,导致追加空数据 - 确认
resultsChunk的分块逻辑是否正确,第二块数据的长度是否为1
内容的提问来源于stack exchange,提问作者Alvinrightback
相关产品推荐
相关产品推荐

