如何在Jest中测试比较innerHTML?执行报错如何解决
问题修复方案
你遇到的错误由两个核心问题导致:
1. 参数取值逻辑错误,导致出现undefined undefined
你在listCurrency.js的setFromCurrency函数中,直接对入参currency执行Object.values(currency)遍历,但你测试时传入的mockCurrency是顶层对象,实际的货币列表存储在mockCurrency.symbols属性下:
你调用Object.values(mockCurrency)得到的结果是[{Symbol: {description: "Country Name", code: "Symbol"}}],遍历得到的每一项是外层的包装对象,自然取不到code和description属性,才会输出undefined undefined。
2. 原始innerHTML直接匹配受格式干扰
JSOM解析HTML时会自动标准化属性格式(比如把onchange = "xxx"中间的空格去掉,变成onchange="xxx"),同时你写的模板字符串自带缩进、换行,直接用toBe对比原始字符串大概率会因为格式差异报错,这种对比方式稳定性极低。
具体修复步骤
步骤1:修正取值逻辑(二选一即可)
- 方案A:修改
listCurrency.js的遍历逻辑,读取symbols属性:
function setFromCurrency(currency) { document.getElementById("initial-currency").innerHTML = ` <select onchange ="getCurrencyA(this.value)"><option>Choose a Currency</option>${Object.values(currency.symbols).map(function (name) {return `<option>${name.code} ${name.description}</option>`}).join("")};</select> `; } module.exports = { setFromCurrency };
- 方案B:测试时直接传入
mockCurrency.symbols:
setFromCurrency(mockCurrency.symbols);
步骤2:改用更稳定的断言方式(推荐)
不要直接对比完整innerHTML字符串,直接校验DOM元素的属性、内容即可,完全不受格式干扰:
test('should give currency list', () => { document.body.innerHTML = `<div id="initial-currency"></div>`; setFromCurrency(mockCurrency); const selectEl = document.querySelector('#initial-currency select'); // 校验select的onchange属性 expect(selectEl.getAttribute('onchange')).toBe('getCurrencyA(this.value)'); // 校验option总数 expect(selectEl.options.length).toBe(2); // 校验默认option内容 expect(selectEl.options[0].textContent.trim()).toBe('Choose a Currency'); // 校验生成的货币option内容 expect(selectEl.options[1].textContent.trim()).toBe('Symbol Country Name'); })
如果一定要对比完整字符串,可以先对两边的字符串做标准化,比如去掉所有空白字符后再对比:
const formatHtml = (str) => str.replace(/\s+/g, '').trim(); expect(formatHtml(fromCurrency.innerHTML)).toBe(formatHtml(currencyStr));
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

