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

使用JSDOM时遭遇ReferenceError: document is not defined问题求助

解决JSDOM测试中document is not defined的问题

问题根源

我一眼就看出问题所在了——你的模块加载时机和JSDOM初始化顺序完全搞反了!当你在测试文件里执行var updateMsg = require('../module.js')时,Node.js会立刻执行整个module.js的所有代码,包括你写在最末尾的updateMsg("Changing message")。但这时候你的before钩子还没运行,global.document还没被JSDOM初始化出来,自然就会抛出ReferenceError: document is not defined的错误。

两种解决方案(结合使用效果最佳)

方案1:让模块仅在浏览器环境下自动执行初始化代码

修改你的module.js,给自动执行的代码加一个环境判断,只有在浏览器(存在window对象)的场景下才运行初始化逻辑:

function updateMsg(newMsg) {
  document.getElementById('msg').innerHTML = newMsg;
}

// 仅在浏览器环境执行初始化(Node环境中window为undefined)
if (typeof window !== 'undefined') {
  updateMsg("Changing message");
}

module.exports = updateMsg;

方案2:调整测试文件的加载顺序,先初始化JSDOM再加载模块

把require('../module.js')移到before钩子内部,确保JSDOM已经把document挂载到全局后,再加载你的业务模块:

const expect = require('chai').expect
const { JSDOM } = require('jsdom');

describe('updateMsg', function () {
  let updateMsg; // 先声明变量占位

  before(function() {
    return JSDOM.fromFile('index.html')
      .then((dom) => {
        global.window = dom.window;
        global.document = window.document;
        // 现在document已经就绪,再加载模块
        updateMsg = require('../module.js');
      });
  })

  it ('updates the innerHTML of element with id "msg"', function () {
    expect(document.getElementById('msg').innerHTML).to.equal('Hello, World!');
    updateMsg('The new msg!');
    expect(document.getElementById('msg').innerHTML).to.equal('The new msg!');
  });
});

额外优化建议

如果你想让代码耦合度更低、测试更灵活,可以把document作为参数传递给updateMsg函数,彻底摆脱对全局document的依赖:

// 修改module.js
function updateMsg(newMsg, doc = document) {
  doc.getElementById('msg').innerHTML = newMsg;
}

// 测试时调用方式
updateMsg('The new msg!', document);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 09:28:41