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

Jest测试submit事件报TypeError: Cannot read property 'value' of undefined如何解决

错误原因

你的selectDestination函数中没有从事件对象的target属性取值,而是直接通过document.querySelector('form')获取页面表单元素。测试运行在Node.js的jsdom环境下,默认没有你写的表单DOM结构,所以querySelector返回null,访问null.destination.value就会抛出"Cannot read property 'value' of undefined"的错误。


解决方案1:不修改原业务代码,测试前挂载DOM

在测试用例执行前,把对应的表单HTML插入到测试环境的DOM中即可,调整后的测试代码如下:

describe('submit event', () => {
  it('listens for event when submit button pressed', () => {
    // 先挂载表单DOM到测试环境,设置默认选中的option值为1
    document.body.innerHTML = `
    <form>
      <label for="event">Choose a destination</label>
      <select name="destination" id="destination">
        <option value="1" selected>Paris</option>
      </select>
      <input id="submit" type="submit">
    </form>
    `
    // 模拟事件只需要带preventDefault即可,原业务代码没有用到e.target
    const fakeE = { preventDefault: jest.fn() }
    // mock全局fetch避免测试时报请求相关错误
    global.fetch = jest.fn(() => 
      Promise.resolve({ json: () => Promise.resolve({}) })
    )

    app.selectDestination(fakeE)
    expect(app.selectDestination).toHaveBeenCalled()
    // 可选补充验证逻辑
    expect(fakeE.preventDefault).toHaveBeenCalled()
    expect(global.fetch).toHaveBeenCalledWith('http://localhost:3000/data/1')
  })
})

解决方案2:优化原业务代码,提升可测试性

直接从提交事件的target获取表单元素(提交事件触发时e.target就是表单本身),不需要全局查询DOM,耦合度更低、可测试性更强,调整后的代码如下:

修改后的业务代码

const selectDestination = (e) => {
  e.preventDefault();
  // 替换原来的document.querySelector逻辑,直接从事件对象取表单
  let form = e.target;
  const destination =  {
    id: form.destination.value
  }
  console.log(destination)

  fetch(`http://localhost:3000/data/${destination.id}`)
  .then(r => r.json())
  .then(appendPrice)
  .catch(console.warn)
}

调整后的测试代码

describe('submit event', () => {
  it('listens for event when submit button pressed', () => {
    const fakeE = {
      preventDefault: jest.fn(),
      target: {
        destination : { value: '1' },
      }
    }
    global.fetch = jest.fn(() => 
      Promise.resolve({ json: () => Promise.resolve({}) })
    )

    app.selectDestination(fakeE)
    expect(app.selectDestination).toHaveBeenCalled()
  })
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 21:06:03