如何在Jasmine中正确Mock THREE.WebGLRenderer避免WebGL上下文创建错误?
解决Jasmine中Mock THREE.WebGLRenderer无效的问题
你之前的mock方式未生效,是因为jasmine.createSpy('THREE.WebGLRenderer')仅创建了一个孤立的间谍函数,并未替换代码里实际调用的THREE.WebGLRenderer构造函数,因此仍会触发原始构造函数的WebGL上下文创建逻辑,导致报错。
以下是针对不同引入场景的修复方案:
场景1:THREE为全局对象(通过script标签引入)
直接替换全局THREE对象上的WebGLRenderer属性为间谍:
// 定义mock的renderer对象,按需添加测试所需的方法/属性 const mockRenderer = { setSize: jasmine.createSpy('setSize'), render: jasmine.createSpy('render') }; // 替换全局THREE.WebGLRenderer为间谍 spyOn(window.THREE, 'WebGLRenderer').and.returnValue(mockRenderer); // 执行测试逻辑 const testElement = document.createElement('div'); yourClassInstance.init(testElement); // 断言验证 expect(window.THREE.WebGLRenderer).toHaveBeenCalledWith({antialias: true}); expect(yourClassInstance.renderer).toBe(mockRenderer);
场景2:通过ES模块引入THREE(import语法)
若代码使用import * as THREE from 'three'引入,直接替换导入对象中的WebGLRenderer:
import * as THREE from 'three'; import YourClass from './path-to-your-class'; describe('YourClass', () => { let mockRenderer: any; beforeEach(() => { // 初始化mock renderer mockRenderer = { setSize: jasmine.createSpy('setSize'), render: jasmine.createSpy('render') }; // 替换THREE.WebGLRenderer为间谍 (THREE.WebGLRenderer as jasmine.Spy) = jasmine.createSpy().and.returnValue(mockRenderer); }); it('should initialize renderer correctly', () => { const instance = new YourClass(); const testElement = document.createElement('div'); instance.init(testElement); expect(THREE.WebGLRenderer).toHaveBeenCalledWith({antialias: true}); expect(instance.renderer).toBe(mockRenderer); }); });
场景3:通过CommonJS引入THREE(require语法)
使用proxyquire工具mock整个three模块:
const proxyquire = require('proxyquire'); const mockRenderer = { setSize: jasmine.createSpy('setSize') }; // 用proxyquire加载目标类,同时mock three模块 const YourClass = proxyquire('./path-to-your-class', { 'three': { WebGLRenderer: jasmine.createSpy().and.returnValue(mockRenderer) } }).default; describe('YourClass', () => { it('should init renderer properly', () => { const instance = new YourClass(); const testElement = document.createElement('div'); instance.init(testElement); expect(require('three').WebGLRenderer).toHaveBeenCalledWith({antialias: true}); expect(instance.renderer).toBe(mockRenderer); }); });
核心要点:必须确保代码中实际调用的THREE.WebGLRenderer被替换为间谍函数,而非创建无关的孤立间谍。测试环境无真实WebGL上下文,需完全mock构造函数,避免触发原始实例化逻辑。
内容的提问来源于stack exchange,提问作者Mini
相关产品推荐
相关产品推荐

