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

使用Jest编写JS单元测试时无法inject/mock document该如何解决?

问题解决方法

1. 修复document is not defined报错

该报错是因为Jest默认运行在Node.js环境,没有浏览器端的document、window等全局对象,同时你的业务代码还依赖全局变量Granite.$,未提前模拟就导入文件会触发报错,解决步骤如下:

  • 安装jsdom环境依赖:
npm install jest-environment-jsdom --save-dev
  • 在项目根目录的jest.config.js中添加配置,指定测试环境为jsdom:
module.exports = {
  testEnvironment: "jsdom",
  // 其余原有配置保持不变
}
  • 在测试文件顶部先模拟全局对象,再导入业务JS文件,避免导入时找不到依赖:
const $ = require('jquery');
// 提前模拟全局Granite对象
global.Granite = { $ };
// 模拟完成后再导入业务代码
require('./你的业务JS文件路径.js');

2. 修复测试用例逻辑错误

你编写的测试存在多处逻辑问题:

  • showHide是业务JS内部定义的函数,没有对外暴露,测试中无法直接访问
  • toBeCalled是Jest spy对象的方法,用来验证被监听的函数是否被调用,不能直接用在普通函数上
  • 构造的测试DOM没有匹配业务逻辑的data-dialog-checkbox-showhide属性元素,无法触发对应逻辑

建议优先测试业务行为而非内部函数调用,无需刻意验证showHide是否被调用,直接验证DOM操作结果即可,测试用例示例如下:

const $ = require('jquery');

global.Granite = { $ };
require('./你的业务JS文件路径.js');

describe("checkboxshowhide 功能测试", () => {
  // 每个测试用例执行前重置DOM
  beforeEach(() => {
    document.body.innerHTML = `
      <input type="checkbox" data-dialog-checkbox-showhide data-dialog-checkbox-showhide-target=".test-target" />
      <div class="test-target-parent">
        <input class="test-target" type="text" />
      </div>
    `;
  })

  test("foundation-contentloaded事件触发时会自动初始化复选框状态", () => {
    // 触发初始化事件
    $(document).trigger('foundation-contentloaded');
    const target = $('.test-target');
    // 默认未勾选状态下,目标元素父容器可见,aria-required为true
    expect(target.attr('aria-required')).toBe('true');
    expect(target.parent().is(':visible')).toBe(true);
  })

  test("复选框勾选时会隐藏目标元素、清空值、关闭必填校验", () => {
    const checkbox = $('[data-dialog-checkbox-showhide]');
    const target = $('.test-target');
    target.val('预设测试内容');
    
    // 勾选复选框触发change事件
    checkbox.prop('checked', true).trigger('change');
    
    expect(target.val()).toBe('');
    expect(target.attr('aria-required')).toBe('false');
    expect(target.parent().is(':visible')).toBe(false);
  })

  test("复选框取消勾选时会显示目标元素、开启必填校验", () => {
    const checkbox = $('[data-dialog-checkbox-showhide]');
    const target = $('.test-target');
    
    // 先勾选再取消
    checkbox.prop('checked', true).trigger('change');
    checkbox.prop('checked', false).trigger('change');
    
    expect(target.attr('aria-required')).toBe('true');
    expect(target.parent().is(':visible')).toBe(true);
  })
});

3. 其他测试扩展指引

  • 边界场景测试:可覆盖单个复选框绑定多个目标元素、复选框默认勾选初始化、动态添加复选框元素等场景
  • 事件监听验证:如果需要验证事件绑定逻辑,可以通过jest.spyOn监听$(document).on方法,验证对应事件的回调是否正确注册
  • 若需要直接测试showHide函数,可以在业务代码的IIFE末尾添加测试环境专属的暴露逻辑,不会影响生产环境运行:
// 业务代码IIFE最后添加
if (process.env.NODE_ENV === 'test') {
  window.checkboxShowHideUtil = { showHide };
}
})(document, Granite.$);

测试中就可以通过window.checkboxShowHideUtil.showHide直接调用函数做单测。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 02:45:03