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

使用Jasmine测试函数时遇TypeError:无法读取undefined的toLowerCase属性

解决Jasmine测试中$('#add_name').val()报undefined的问题

你遇到的这个问题其实是Jasmine新手很容易踩的坑:你的check_names函数直接依赖DOM元素#add_name,但在Jasmine的测试环境里,这个元素根本不存在,所以调用$('#add_name').val()自然会得到undefined,后续的.toLowerCase()还会引发报错。而且你测试代码里定义的name = "add"也没起作用,因为函数根本没用到这个变量,还是硬去读DOM的值。

下面给你拆解问题和修复方案:

问题根源

你的业务逻辑(检查数组、添加元素)和DOM操作(读取输入框值)耦合在一起了。Jasmine默认是在一个干净的测试沙箱环境里运行,没有你页面上的#add_name输入框,所以jQuery找不到这个元素,.val()就返回undefined。

最优修复方案:解耦DOM与业务逻辑

把读取输入框的逻辑从check_names里抽出来,让函数只负责处理数组相关的业务逻辑,通过参数接收name值。这样函数更纯粹,也更容易测试。

修改后的业务逻辑函数

function check_names(names_array, name) {
  // 先处理空值情况,避免报错
  if (!name) return false;
  
  const lowerCaseName = name.toLowerCase();
  // 检查名字是否存在
  if (names_array.includes(lowerCaseName)) {
    return true;
  } else {
    // 不存在就加入数组
    names_array.push(lowerCaseName);
    return false;
  }
}

// 单独写处理DOM交互的函数
function handleNameSubmission() {
  const namesArray = ["add","bad","sad","dad"];
  const inputName = $('#add_name').val();
  const nameExists = check_names(namesArray, inputName);
  
  if (!nameExists) {
    // 这里写追加表格行的逻辑
    $('table').append(`<tr><td>${inputName.toLowerCase()}</td></tr>`);
  }
}

更新后的Jasmine测试代码

现在测试时直接传入需要的name值,完全不需要依赖DOM,测试更稳定:

describe("On Name Create", function () {
  let namesArray;

  // 每个测试前重置数组,避免测试之间互相干扰
  beforeEach(function () {
    namesArray = ["add","bad","sad","dad"];
  });

  it("returns true when the name already exists in the array", function () {
    expect(check_names(namesArray, "add")).toBeTruthy();
  });

  it("returns false and adds the name to the array when it doesn't exist", function () {
    const newName = "mad";
    expect(check_names(namesArray, newName)).toBeFalsy();
    expect(namesArray).toContain(newName.toLowerCase());
  });

  it("handles case insensitivity correctly", function () {
    expect(check_names(namesArray, "ADD")).toBeTruthy();
  });
});

备选方案:模拟DOM元素(不推荐,但适合快速调试)

如果你暂时不想重构函数,也可以在测试中手动创建DOM元素,让jQuery能找到它:

describe("On Name Create", function () {
  let namesArray;

  beforeEach(function () {
    namesArray = ["add","bad","sad","dad"];
    // 在测试前把输入框加到页面上
    $('body').append('<input type="text" id="add_name">');
  });

  afterEach(function () {
    // 测试结束后清理DOM,避免影响其他测试
    $('#add_name').remove();
  });

  it("returns true when name exists", function () {
    // 给输入框设值
    $('#add_name').val("add");
    expect(check_names(namesArray)).toBeTruthy();
  });
});

总结

作为Jasmine新手,你遗漏的核心点是测试环境没有你页面上的DOM元素,而且函数和DOM耦合太紧导致测试困难。把业务逻辑和DOM操作分开是前端测试的最佳实践,这样测试只需要关注核心逻辑,代码也更易维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:21:36