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

Jest中模拟DOMPoint时行为不一致的问题排查

问题分析与解决方案

你的核心问题是:Jest的mock构造函数在测试用例中未执行实现逻辑,但模拟本身已生效(未报未定义错误)。根源在于jest.fn().mockImplementation作为构造函数使用时,会受Jest的mock重置机制影响,且jsdom环境下全局对象的属性绑定需要更贴合原生API的方式。

问题原因

  1. Jest默认会在每个测试用例执行后重置mock函数(包括mockImplementation的逻辑),导致setup文件中定义的mock实现到测试用例中被清空。
  2. 用Object.defineProperty绑定jest.fn()作为构造函数,不如直接定义类更贴合原生DOMPoint/DOMRect的行为,容易出现上下文或执行时机问题。
  3. 你未模拟DOMRect的完整属性(如top/right/bottom/left计算属性),后续几何函数可能也会失效。

正确的模拟方案

替换setup文件中的模拟代码为类定义,直接赋值给全局对象,避免依赖Jest的mock函数机制:

// setupUnitTests.ts
// 模拟DOMPoint
globalThis.DOMPoint = class DOMPoint {
  x: number;
  y: number;
  z: number;
  w: number;

  constructor(x?: number, y?: number, z?: number, w?: number) {
    this.x = x ?? 0;
    this.y = y ?? 0;
    this.z = z ?? 0;
    this.w = w ?? 0;
  }

  matrixTransform = jest.fn();
  toJSON = jest.fn();
};

// 模拟DOMRect(需实现标准计算属性)
globalThis.DOMRect = class DOMRect {
  x: number;
  y: number;
  width: number;
  height: number;

  constructor(x?: number, y?: number, width?: number, height?: number) {
    this.x = x ?? 0;
    this.y = y ?? 0;
    this.width = width ?? 0;
    this.height = height ?? 0;
  }

  // 原生DOMRect的标准计算属性
  get top() { return this.y; }
  get right() { return this.x + this.width; }
  get bottom() { return this.y + this.height; }
  get left() { return this.x; }
};

验证步骤

  1. 确保jest.config.ts中setupFilesAfterEnv正确指向该setup文件:
    export default {
      setupFilesAfterEnv: ['<rootDir>/src/setupUnitTests.ts'],
      // 其他配置...
    };
    
  2. 删除测试用例中自行添加的模拟代码,保持全局模拟的统一性。
  3. 运行测试,此时DOMPoint和DOMRect实例会正常初始化,且几何函数依赖的属性(如DOMRect的top/left)也能正常工作。

额外说明

如果一定要使用Jest的mock函数,需要在jest配置中关闭自动重置mock:

// jest.config.ts
export default {
  resetMocks: false,
  // 其他配置...
};

但直接定义类的方式更稳定,完全贴合原生API的结构,不会受Jest的mock机制限制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 21:50:33