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

React测试遇TypeError: Cannot read properties of undefined(reading 'includes')问题求助

问题

运行React测试时遭遇TypeError: Cannot read properties of undefined (reading 'includes')错误,测试卡在第26行。注释该行后测试能正常返回预期结果,保留则触发错误。调试发现contentType的值为undefined,但不知道如何在测试中处理这种情况。

完整错误信息:

● display data › should render data 

    TypeError: Cannot read properties of undefined (reading 'includes')

      24 |   const lastIndex = currentPage * productsPerPage;
      25 |   const firstIndex = lastIndex - productsPerPage;
    > 26 |     const productsByContentType = products.filter((type: Products) => type.contentType.includes(contentTypeValue))  || products;
         |                                                                                        ^
      27 |   const filteredProducts = sortBy?.[filterValue]?.(productsByContentType) ?? productsByContentType;
      28 |
      29 |   const productsBySearchValue = filteredProducts.filter((search: Products) => {

测试代码:

describe('display data', () => {
  afterEach(() => {
    jest.restoreAllMocks();
  });
  test('should render data', async () => {
    const mAxiosResponse = {
      data: [{title: "5-Minute Stories: In the Wild"}],
    } as AxiosResponse;
    jest.spyOn(axios, 'get').mockResolvedValueOnce(mAxiosResponse);
    render(<Landing />);
    expect(screen.getByText('Loading...')).toBeInTheDocument();
    expect(await screen.findByDisplayValue('Name:')).toBeInTheDocument();
    
  });
});

组件核心代码:

function App() {
  const [products, setProducts] = useState<Products[]>([]);
  const [contentTypeValue, setContentTypeValue] = useState<string>('Stories');

  // ...其他状态定义

  const productsByContentType = products.filter((type: Products) => type.contentType.includes(contentTypeValue))  || products;
  
  // ...其他过滤、排序逻辑

  const fetchData = async () => {
    axios.get('http://localhost:3030/products')
    .then((res: AxiosResponse<Products[]>) => {
      setProducts(res.data);
    })
    .catch((err) => console.log(err))
    };
    
  useEffect(() => {
    fetchData()
    setSearchValue('');
  }, []);

  // ...其他渲染逻辑
}

解决方案

1. 修复组件空值安全问题

错误根源是type.contentType可能为undefined,调用includes前必须先做空值校验。修改第26行的过滤逻辑:

const productsByContentType = products.filter((type: Products) => 
  type.contentType?.includes(contentTypeValue) ?? false
) || products;

使用可选链?.规避contentType为undefined的情况,再通过?? false确保空值时返回false,不会触发过滤。

同时建议同步修复搜索逻辑中的同类问题:

const productsBySearchValue = filteredProducts.filter((search: Products) => {
  return search.title?.toLowerCase().includes(searchValue) ?? false;
}) || filteredProducts;

2. 完善测试Mock数据

测试返回的Mock数据缺少contentType字段,导致组件处理时出现undefined。更新测试的响应数据:

const mAxiosResponse = {
  data: [{
    title: "5-Minute Stories: In the Wild",
    contentType: "Stories", // 补充必填的contentType字段
    id: 1,
    price: 9.99,
    productType: "Book",
    imgSet: { sm: { src: "test-image.jpg" } }
  }],
} as AxiosResponse;

补充Products类型要求的完整字段,确保组件能正常处理数据,避免因字段缺失引发错误。

3. 新增边界场景测试

可以添加测试用例,验证组件在contentType为undefined时的稳定性:

test('should handle products with undefined contentType', async () => {
  const mAxiosResponse = {
    data: [
      {title: "Test Product", contentType: undefined, id: 2, price: 19.99, productType: "E-book", imgSet: { sm: { src: "test.jpg" } }},
      {title: "Story Product", contentType: "Stories", id: 3, price: 12.99, productType: "Book", imgSet: { sm: { src: "test2.jpg" } }}
    ],
  } as AxiosResponse;
  jest.spyOn(axios, 'get').mockResolvedValueOnce(mAxiosResponse);
  render(<Landing />);
  
  // 验证组件正常渲染无崩溃
  expect(await screen.findByText('Name: Test Product')).toBeInTheDocument();
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 10:17:32