专家级JavaScript单元测试需建立三层能力:理解测试本质、深度掌控工具链、本能设计可测性;具体体现为四点——验契约而非仅测结果、mock即声明交互协议、测试结构可维护、测试驱动架构优化。

想真正掌握 JavaScript 单元测试的专家级技巧,关键不在“多写几个 test”,而在于建立三层能力:对测试本质的理解、对工具链的深度掌控、以及对代码可测性的本能设计意识。下面这四点,是跨过中级、走向专家的分水岭。
一、从“测结果”升级到“验契约”
初级测试关注“这个函数返回 5 对不对”,专家级测试则定义“它在任何合法输入下都必须满足什么不变量”。比如:
- 排序函数不只测
[2,1]→[1,2],还要用 Fast-Check 自动生成上千种边界组合(空数组、重复值、负数、极大值),验证“输出始终升序且长度不变” - 状态管理函数不只测
setState({a:1})→{a:1,b:0},还要断言“所有未传字段保持原值”“返回新对象而非修改原对象”
二、Mock 不是“绕过依赖”,而是“声明交互协议”
专家写 mock,会像写接口文档一样严谨:
- 用
vi.mock('./api', () => ({ fetchUser: vi.fn().mockResolvedValue(...) }))显式声明返回值,而不是靠jest.mock()全局替换后在测试里临时改 - 对定时器、随机数、时间等副作用,统一抽象为可注入依赖(如
clock: { now: () => number }),测试时注入固定时间戳,让异步逻辑完全可控 - 每个 mock 都配清理逻辑:
afterEach(() => vi.clearAllMocks()),避免测试间隐式污染
三、测试结构本身要可维护,不输业务代码
专家的测试文件不是一堆 it 堆砌,而是有清晰组织:
- 按行为分组:
describe('when user is logged in'/'when network fails',而不是按函数名 - 复用 setup 逻辑:用
beforeEach构建标准上下文,但避免过度封装导致调试困难 - 测试命名直指意图:
it('retries 3 times on network timeout',而不是'test retry logic'
四、把测试变成架构反馈系统
专家会从测试难易度反推代码质量:
- 发现某个模块很难 mock?说明它没做依赖抽象,立刻补上接口或参数注入点
- 总要
vi.mock七八个东西才能测一个函数?说明职责过重,该拆了 - 一个测试要等 200ms 才跑完?说明混入了真实 I/O,得把延迟、请求、存储全抽成可替换依赖
测试写得越“别扭”,越是在提醒你:这里的设计需要重构。这种敏感度,才是专家和熟手的本质区别。


















