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

使用Jasmine/Karma测试操作DOM的JS函数时遇变量未定义报错求助

解决Jasmine+Karma测试DOM操作函数的ReferenceError问题

嘿,我看了你刚接触JS单元测试时遇到的问题,用Jasmine和Karma测试setRenderer函数时出现了ReferenceError: threeD is not defined的报错,咱们一步步拆解问题并解决它~

问题根源分析

我梳理了你的代码后,发现两个关键问题:

  1. 变量未声明触发严格模式报错:你的setRenderer函数里,threeD和renderer变量直接赋值但没有用let/const/var声明。Karma通常默认启用严格模式,在严格模式下,未声明的变量赋值会直接抛出ReferenceError,而不是自动创建全局变量——这就是你看到报错的核心原因。
  2. 测试代码的语法小错误:你的测试用例里,expect语句多了一个左括号,虽然这不是当前报错的直接原因,但不修复的话后续也会阻碍测试执行。

修复步骤

1. 先修复setRenderer函数的变量声明

打开你的renderer.js文件,给未声明的变量加上声明:
如果threeD和renderer只是函数内部使用的变量,修改成这样:

export function setRenderer() { 
  let threeD = document.getElementById('container'); 
  let renderer = new THREE.WebGLRenderer({ 
    antialias: true, 
    alpha: true, 
  }); 
  renderer.setSize(threeD.clientWidth, threeD.clientHeight); 
  let blueColor = 0x607d8b; 
  let alpha = 1; 
  renderer.setClearColor(blueColor, alpha); 
  threeD.appendChild(renderer.domElement); 
}

如果这两个变量需要供模块内其他函数调用,就把声明移到函数外部:

let threeD;
let renderer;

export function setRenderer() { 
  threeD = document.getElementById('container'); 
  renderer = new THREE.WebGLRenderer({ 
    antialias: true, 
    alpha: true, 
  }); 
  // 后续代码保持不变
}

2. 修复测试代码并优化测试逻辑

修改你的测试代码,修复语法错误,同时添加测试前后的DOM环境处理,保证测试独立性:

/* globals describe, it, expect, beforeEach, afterEach*/ 
import {setRenderer} from '../../lessons/04/renderer';

describe('Configuration', () => { 
  it('should true be true', () => { 
    expect(true).toBe(true); 
  }); 
}); 

describe('Renderer', () => { 
  let containerDiv;

  beforeEach(() => {
    // 测试前创建container元素,顺便设置宽高避免renderer获取到0尺寸
    containerDiv = document.createElement("div");
    containerDiv.id = 'container';
    containerDiv.style.width = '800px';
    containerDiv.style.height = '600px';
    document.body.appendChild(containerDiv);
  });

  afterEach(() => {
    // 测试后清理DOM,避免影响其他测试用例
    document.body.removeChild(containerDiv);
  });

  it('should be created', () => { 
    setRenderer(); 
    // 修复语法错误:把多余的左括号去掉,正确闭合expect
    expect(document.getElementById('container')).toBe(containerDiv);
    // 还可以加个额外测试,验证renderer的canvas是否被正确添加
    expect(containerDiv.children.length).toBe(1);
    expect(containerDiv.firstChild.tagName).toBe('CANVAS');
  }); 
});

额外小提示

  • 给测试用的container设置宽高是因为renderer.setSize依赖元素的clientWidth和clientHeight,如果不设置,这两个值会是0,虽然不影响当前测试,但后续如果要测试renderer的尺寸,这个设置就很有必要了。
  • 用afterEach清理DOM是单元测试的最佳实践,能确保每个测试用例都在干净的环境中运行,不会互相干扰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:59:06