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

Jest+JSDOM切换beforeAll为beforeEach后第二个测试失败

问题原因分析

核心问题出在Jest的模块缓存机制和测试代码中重复引入业务脚本的方式上:

  • 当你使用beforeEach时,每次测试都会执行代码块,但Jest会对require/import的模块做缓存——第一次引入业务脚本(比如app.js)时,脚本里的事件绑定代码会执行,给当时的按钮绑定点击事件;但第二次require时,因为模块已经被缓存,脚本代码不会重新执行,而此时你已经通过innerHTML重置了DOM,新生成的按钮根本没有绑定事件,导致测试点击按钮后没有任何反应,自然失败。
  • 单独运行第二个测试时,模块缓存是空的,require会重新执行业务脚本,新按钮能正常绑定事件,所以测试通过。
  • 改用beforeAll时,DOM只初始化一次,事件也只绑定一次,两个测试共用同一批DOM元素,所以不会出现问题。
解决方法
  • 每次测试时强制清除模块缓存:在beforeEach里引入业务脚本前,先删除Jest的模块缓存,确保脚本每次都重新执行:
    beforeEach(() => {
      document.body.innerHTML = `
        <button id="textBtn">Change Text</button>
        <button id="colorBtn">Change Color</button>
        <p id="text">Hello</p>
      `;
      // 清除对应模块的缓存
      delete require.cache[require.resolve('./app.js')];
      require('./app.js');
    });
    
  • 重构业务代码,支持重复初始化:把事件绑定逻辑封装成一个函数,比如init(),在业务脚本里暴露这个函数,然后在测试的beforeEach里调用init(),而不是重复引入整个模块:
    // 业务脚本 app.js
    export function init() {
      document.getElementById('textBtn').addEventListener('click', () => {
        document.getElementById('text').textContent = 'Changed';
      });
      document.getElementById('colorBtn').addEventListener('click', () => {
        document.body.style.backgroundColor = 'red';
      });
    }
    // 如果是CommonJS:
    // module.exports = { init };
    
    // 测试代码
    beforeEach(() => {
      document.body.innerHTML = `
        <button id="textBtn">Change Text</button>
        <button id="colorBtn">Change Color</button>
        <p id="text">Hello</p>
      `;
      const { init } = require('./app.js');
      init();
    });
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 20:50:35