GitLab流水线Jest测试报错:TypeError: Cannot read properties of null (reading 'value'),如何解决?
解决Jest测试中
TypeError: Cannot read properties of null (reading 'value')问题 问题根源
Jest默认运行在Node.js环境中,没有浏览器的DOM环境,你的checkInputs函数直接通过document.getElementById('password')获取元素时会返回null,访问null.value自然会抛出类型错误。GitLab流水线的运行环境和本地Jest环境一致,因此会出现相同报错。
解决方案
1. 配置Jest使用jsdom模拟DOM环境
Jest 27+默认使用node环境,需手动切换为jsdom。在package.json中添加Jest配置:
"jest": { "testEnvironment": "jsdom" }
2. 在测试文件中模拟所需DOM元素
在测试代码执行前,手动插入需要的DOM节点,让document.getElementById能获取到有效元素:
// 测试文件开头:插入模拟的DOM结构 document.body.innerHTML = ` <input type="password" id="password" value="test123"> <!-- 加上触发checkInputs的元素,比如提交按钮 --> <button id="submit-btn">Submit</button> `; // 导入目标函数 const { checkInputs } = require('./script'); test('checkInputs 被正确调用', () => { // 用jest.spyOn mock函数,方便检测调用情况 const mockCheckInputs = jest.spyOn(window, 'checkInputs').mockImplementation(() => {}); // 触发调用checkInputs的动作(比如按钮点击) document.getElementById('submit-btn').click(); // 断言函数被调用 expect(mockCheckInputs).toHaveBeenCalled(); // 清理mock,避免影响其他测试 mockCheckInputs.mockRestore(); });
3. 重构函数,解耦DOM依赖(推荐)
把业务逻辑和DOM操作分离,让函数更易测试,同时避免线上环境潜在的空值报错:
// script.js // 独立的校验逻辑,不依赖DOM function validatePassword(password) { return password.length >= 6; } // 处理DOM的函数,增加空值判断 function checkInputs() { const passwordInput = document.getElementById('password'); if (!passwordInput) return; // 空值兜底,避免报错 const isValid = validatePassword(passwordInput.value); // ...后续业务逻辑 } // 导出供测试使用 module.exports = { checkInputs, validatePassword };
你可以单独测试validatePassword函数,也能在测试checkInputs时更灵活地模拟DOM场景。
4. 函数调用检测的简化方式
如果只是单纯要验证checkInputs是否被调用,可直接mock函数,不需要执行完整逻辑:
test('checkInputs 被调用', () => { // 全局mock checkInputs函数 window.checkInputs = jest.fn(); // 触发调用动作(比如模拟事件或直接调用) window.checkInputs(); expect(window.checkInputs).toHaveBeenCalled(); });
总结
核心思路就是给Jest提供模拟的DOM环境,或者让函数不直接依赖DOM。GitLab流水线的运行逻辑和本地Jest一致,只要本地测试通过,流水线就能正常执行。
内容的提问来源于stack exchange,提问作者Željko
相关产品推荐
相关产品推荐

