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

Jest测试React组件时出现TypeError:无法读取null的'title'属性

解决测试中出现的TypeError: Cannot read property 'title' of null问题

我来帮你分析一下这个问题的根源,以及对应的修复方案:

问题原因

1. 测试中Mock的Response缺少status属性

你的测试代码里mock了fetch,但返回的Response对象没有设置status属性。在useAPI.ts的CallAPI函数里,只有当response.status ===200时才会把接口返回的json赋值给returnResponse.data。因为mock的Response没有status,这个判断条件不成立,所以returnResponse.data一直是初始的null。当组件调用setState({ postResponse : res })后,this.state.postResponse.data就变成了null,访问null.title自然就抛出了TypeError。

2. useAPI中存在全局变量污染问题

returnResponse是一个全局变量,每次调用CallAPI都会修改同一个对象。这会导致多次调用时状态互相污染,比如第一次调用成功后,data会保留下来,后续如果调用失败,返回的data还是之前的成功数据,这不仅是测试中的潜在问题,也是生产环境的bug。

修复方案

第一步:修复测试中的Mock逻辑

给mock的Response添加status:200,确保CallAPI里的判断条件能触发,同时删掉冗余的mock代码:

// MultipleFetches.test.tsx
test("post shows correct title after button click", async () =>{
 const utils = render(<MultipleFetches/>)
 const data ={
 userId: 1,
 id: 1,
 title: "Mock Title",
 body: "Mocked Body"
 }
 // 只保留这一段mock代码即可
 jest.spyOn(global,'fetch')
 .mockImplementation(() => Promise.resolve({
  status: 200, // 新增status属性
  json: () => Promise.resolve(data)
 } as Response))
 const button = utils.getByTestId("post-click");
 fireEvent.click(button);
 const newPostTitle = await waitFor(() => utils.getByTestId("post-title"))
 expect(newPostTitle.textContent).toBe("Mock Title");
})

第二步:修复useAPI的全局变量问题

每次调用CallAPI时创建新的响应对象,避免全局状态污染:

// useAPI.ts
export async function CallAPI(url : string){
  // 每次调用都创建新的响应对象
  const returnResponse ={
    data: null,
    success: false,
    error: null
  };
  try{
    const response = await fetch(url);
    if (response.status < 200 || response.status >= 300)
      throw new Error("Failed to fetch");
    const json = await response.json();
    returnResponse.data = json;
    returnResponse.success = true;
  } catch(e){
    // 更严谨的错误类型处理
    returnResponse.error = e instanceof Error ? e.message : String(e);
  }
  return returnResponse;
}

第三步:优化组件的类型和渲染逻辑

  1. 调整State接口,允许data为null,避免类型不匹配:
// MultipleFetches.tsx
interface State{
 postResponse :{
  data: {
    userId: number,
    id: number,
    title: string,
    body:string
  } | null, // 允许data为null
  success : boolean,
  error: string | null // error可以是字符串或null
 }
}
  1. 在渲染时处理data为null的情况,确保即使data是null也不会报错,显示空字符串:
<p data-testid="post-title">{this.state.postResponse.data?.title || ""}</p>

这样修改后,测试就能正常通过,同时生产环境的代码也更健壮,不会因为接口异常或者调用顺序问题出现意外的null报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:27:56