字符串单元测试关键在于验证业务规则下的正确性,需覆盖null/undefined、空串、特殊字符、超长字符串等边界场景,强调语义断言、类型与引用检查,并用fast-check生成高变异测试数据。

对字符串处理函数做单元测试,关键不是“它能不能跑”,而是“它在各种真实输入下是否按业务规则产出正确结果”。字符串看似简单,但隐式转换、空值混淆、Unicode 边界、不可变性误用等问题极易埋下静默漏洞。
覆盖易被忽略的字符串边界输入
别只测 "hello" 和 "world"。真实场景中,字符串常处于“几乎为空”或“结构异常”的状态:
-
null / undefined:检查函数是否提前报错,还是悄悄转成
"null"或"undefined"(比如str.trim()在undefined上会抛错,而String(str).trim()不会) -
空字符串
""、空白串"\t\n "、全空格串:验证清理逻辑是否彻底,比如去首尾空格后是否真为空,而不是留一个" " -
特殊字符:含
\0、、代理对(如 emoji ?)、零宽空格\u200B的字符串,测试.length、.slice()、正则匹配是否失准 -
超长字符串:传入 100 万字符,看是否内存溢出或性能骤降(尤其涉及
.split('')或循环遍历的函数)
围绕字符串业务意图写断言
避免写“JS 引擎测试”,例如 expect("a"+"b").toBe("ab")。每个测试应映射一条明确语义规则:
- 若函数用于生成 URL 路径段,需断言:
result不含空格、不以/开头、不包含..或.连续出现 - 若函数用于截断显示文本(如“最多 20 字,超长加…”),要验证:
result.length ≤ 22,且末尾为"…"时原字符串确实超长 - 若函数解析 CSV 字段(如去除包围的双引号),需用
Object.is(result, expected)断言是否严格相等,防"0"与0混淆
揪出“没报错却做错事”的静默行为
字符串操作错误常不抛错,但破坏数据完整性:
- 对返回值用
typeof result === 'string'显式断言类型,防意外返回null或undefined - 若函数声称“返回新字符串”,用
expect(result).not.toBe(input)确保未复用原引用(验证不可变性遵守) - 处理大小写转换时(如
toTitleCase),用expect(result).toMatch(/^[A-Z]/)+expect(result).not.toMatch(/[A-Z]{2}/)组合断言格式,而非只看首字母 - 涉及正则替换的函数,传入含捕获组的字符串,验证是否污染全局
RegExp.lastMatch(虽已废弃,但旧环境仍需考虑)
用 Fast-Check 自动生成难覆盖的字符串组合
手动枚举所有边界太耗时。Fast-Check 可自动构造高变异字符串:
- 生成含控制字符的串:
fc.string({ minLength: 0, maxLength: 10, charset: fc.char().filter(c => !/\s/.test(c)) }) - 生成带 emoji 和 RTL 标记的混合串:
fc.string({ charset: fc.constantFrom('??', '\u202E', 'a', '1') }).array({ minLength: 1, maxLength: 5 }) - 定义属性断言:“截断函数返回长度永远 ≤ 给定 limit”:
property(fc.string(), fc.integer({ min: 1, max: 100 }), (str, limit) => truncate(str, limit).length
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











