使用Jest与Enzyme测试待办列表新增功能时遇map未定义错误求助
解决Jest/Enzyme测试待办列表新增功能的问题
首先,咱们先搞定那个Cannot read property 'map' of undefined的错误——这是因为你的ListItems组件直接对props.items调用map,但如果组件初始化时没有收到items属性(比如测试时单独渲染它却没传props),items就是undefined,自然会报错。
第一步:修复ListItems组件的防错处理
给items设置一个默认值,或者在map之前做空值判断,双重保险:
function ListItems(props){ // 方法1:设置组件默认props,确保items始终是数组 ListItems.defaultProps = { items: [] }; const items= props.items; // 方法2:用可选链操作符,避免undefined调用map const listItems = items?.map(item => { return <div className="list" key={item.id}> <p> <input type="checkbox" onClick={ () => props.handleClickbox(item.id)} /> <input style={{ color:"white", textDecoration: item.completed ? "line-through":null}} type="text" id={item.id} value={item.task} onChange ={ (e) =>{ props.setUpdate(e.target.value, item.id) } }/> <span> <FontAwesomeIcon className="faicons" icon='trash' onClick={ () => props.deleteItem(item.id) } /> </span> </p> </div> }) return( <div> <FlipMove duration={500} easing="ease-in-out" > {listItems} </FlipMove> </div> ) }
第二步:正确测试新增功能的完整流程
你的测试思路有问题:新增待办是App组件的完整交互流程,需要在App的上下文中模拟输入、提交,然后验证ListItems里是否出现了新项,而不是单独渲染ListItems或者直接查文档。
用Enzyme编写的测试案例
import React from 'react'; import { mount } from 'enzyme'; import App from './App'; import ListItems from './ListItems'; describe('Todo App Add Item Functionality', () => { it('should add a new todo item when form is submitted', () => { // 用mount而不是shallow,因为需要测试组件间的交互(表单提交→state更新→ListItems渲染) const wrapper = mount(<App />); // 1. 模拟输入框输入内容 const input = wrapper.find('#toDoInputId'); input.simulate('change', { target: { value: 'testFirst' } }); // 2. 模拟表单提交,要手动模拟preventDefault避免默认刷新行为 const form = wrapper.find('#to-do-form'); form.simulate('submit', { preventDefault: () => {} }); // 3. 验证App的state是否正确更新 expect(wrapper.state('items')).toContainEqual(expect.objectContaining({ task: 'testFirst', completed: false, id: expect.any(Number) // 如果你的id是自动生成的,用这个匹配任意数字/字符串 })); // 4. 验证ListItems里是否渲染了新的待办项 const listItemInputs = wrapper.find('.list input[type="text"]'); expect(listItemInputs.last().props().value).toBe('testFirst'); }); });
用React Testing Library编写的测试案例
如果习惯用React Testing Library,代码会更简洁:
import React from 'react'; import { render, screen, fireEvent } from '@testing-library/react'; import App from './App'; test('adds a new todo item successfully', () => { render(<App />); // 找到输入框并输入内容 const input = screen.getByPlaceholderText('Enter task'); fireEvent.change(input, { target: { value: 'testFirst' } }); // 找到提交按钮并点击 const submitBtn = screen.getByText('Add'); fireEvent.click(submitBtn); // 验证新项是否出现在页面中 expect(screen.getByDisplayValue('testFirst')).toBeInTheDocument(); });
你之前测试失败的核心原因
- 单独渲染
ListItems却没传itemsprops,直接触发了map的错误; - 没有在App的上下文中模拟完整的「输入→提交」流程,导致测试环境里根本没有渲染出更新后的待办项;
- 用
shallow渲染App无法捕获子组件的状态更新,建议用mount(Enzyme)或React Testing Library的render。
内容的提问来源于stack exchange,提问作者akinov
相关产品推荐
相关产品推荐

