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; }
第三步:优化组件的类型和渲染逻辑
- 调整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 } }
- 在渲染时处理data为null的情况,确保即使data是null也不会报错,显示空字符串:
<p data-testid="post-title">{this.state.postResponse.data?.title || ""}</p>
这样修改后,测试就能正常通过,同时生产环境的代码也更健壮,不会因为接口异常或者调用顺序问题出现意外的null报错。
内容的提问来源于stack exchange,提问作者Appel Taart
相关产品推荐
相关产品推荐

