使用Jest和Enzyme测试React组件内generateCheckboxes函数报错求助
问题:测试React组件的generateCheckboxes函数时出现TypeError错误
问题场景
我在React组件中定义了一个generateCheckboxes函数,用来根据传入的数组生成复选框列表,组件里调用这个函数的逻辑看起来没问题,但用Jest和Enzyme写测试用例时却抛出了类型错误。
组件中的函数定义
const generateCheckboxes = (array, filterType) => { return array.map((filter, i) => { if (!isNullOrUndefined(filter) && filter !== "") { const applied = props.appliedFilterList[filterType].includes(filter); return ( <Row key={i} noLine={i === 0}> <Checkbox checked={applied} onClick={() => props.toggleFilter(filterType, filter)}> {filter} </Checkbox> </Row> ); } return false; }); };
组件内调用方式
return ( <div> <div> {generateCheckboxes(props.accessFilters, "access")} </div> <div> {generateCheckboxes(props.bandwidthFilters, "bandwidth")} </div> </div> );
测试代码
const accessFilters = ["Access Type Of The Service", { length: 1 }]; const bandwidthFilters = ["the allowed band width", "the allowed band width", { length: 2 }]; describe("test the component", () => { const wrapper = mount(<FilterDropdownContent accessFilters={accessFilters} bandwidthFilters={bandwidthFilters} />); it("checks the generateCheckBoxes function", () => { expect(wrapper.instance.generateCheckboxes(accessFilters, "access").toBe(true)); }); });
错误信息
TypeError: Cannot read property 'access' of undefined at array.map (src/site-product/components/FilterDropdownContent.js:12:105) at Array.map (
)
错误指向函数中的这一行:
const applied = props.appliedFilterList[filterType].includes(filter);
问题分析
你的问题出在两个核心点:
- 测试时缺少必要Props:挂载
FilterDropdownContent组件时,只传入了accessFilters和bandwidthFilters,但完全没传appliedFilterList和toggleFilter这两个generateCheckboxes函数依赖的Props。函数里尝试访问props.appliedFilterList["access"],但appliedFilterList本身是undefined,自然就会抛出"无法读取undefined的access属性"的错误。 - 测试断言逻辑错误:
generateCheckboxes函数返回的是React元素数组(或夹杂false的数组),你断言它toBe(true)完全不符合函数的实际返回值,这根本不是你想要验证的结果。
解决步骤
1. 给测试组件传入完整的必要Props
挂载组件时,必须补上appliedFilterList和toggleFilter这两个依赖项,比如用Jest模拟toggleFilter函数,初始化appliedFilterList为包含对应类型空数组的对象:
const accessFilters = ["Access Type Of The Service", { length: 1 }]; const bandwidthFilters = ["the allowed band width", "the allowed band width", { length: 2 }]; const mockToggleFilter = jest.fn(); // 模拟toggleFilter函数 describe("test the component", () => { const wrapper = mount( <FilterDropdownContent accessFilters={accessFilters} bandwidthFilters={bandwidthFilters} appliedFilterList={{ access: [], bandwidth: [] }} // 初始化对应类型的空数组 toggleFilter={mockToggleFilter} /> ); // ... 后续测试逻辑 });
2. 修正测试断言的逻辑
你应该测试函数生成的复选框是否符合预期,比如有效复选框的数量、显示的文本、选中状态等,而不是断言返回值为true。举个例子:
it("generates correct checkboxes for access filters", () => { const result = wrapper.instance().generateCheckboxes(accessFilters, "access"); // 过滤掉数组中返回false的无效项 const validCheckboxes = result.filter(item => item !== false); // 验证有效复选框的数量:accessFilters里只有第一个字符串是有效项 expect(validCheckboxes.length).toBe(1); // 验证第一个复选框的文本内容 expect(validCheckboxes[0].props.children).toBe("Access Type Of The Service"); // 验证复选框的初始选中状态(因为appliedFilterList.access是空数组,所以应该未选中) expect(validCheckboxes[0].props.children.props.checked).toBe(false); });
3. 优化函数的健壮性(可选)
为了避免未来再出现类似的未定义错误,可以给appliedFilterList和对应类型的数组加上可选链和默认值,让函数更容错:
const applied = (props.appliedFilterList?.[filterType] || []).includes(filter);
这样即使appliedFilterList或者对应的filter类型数组不存在,也会用空数组来判断,不会抛出错误。
内容的提问来源于stack exchange,提问作者pranami
相关产品推荐
相关产品推荐

