js单元测试规范需与项目代码规范对齐,强调可读、可维护、可信任;遵循aaa结构、显式mock、语义化断言、边界覆盖及工程化约束。

JS 单元测试代码规范不是独立存在的,它必须和项目整体的 JavaScript 代码规范对齐,核心是让测试代码本身具备可读、可维护、可信任的特质。重点不在“写多少测试”,而在于“每一条测试是否清晰表达意图、稳定可靠、易于演进”。
测试文件与结构统一
保持测试组织方式一致,降低团队理解成本。
- 文件命名严格使用 .test.js 或 .spec.js 后缀(如
utils.test.js),确保测试运行器自动识别 - 测试文件与被测源码放在同一目录(如
src/utils/formatDate.js对应src/utils/formatDate.test.js),避免跨层引用路径混乱 - 用 describe() 按功能模块或函数名分组,每个 describe 描述一个明确上下文(如
describe('formatDate()', () => { ... })) - 每个 test() 只验证一个具体行为,名称用完整句子,以动词开头、含输入和预期(如
test('returns "2023-01-01" for new Date(2023, 0, 1))
测试逻辑编写有章法
测试代码不是自由发挥,它需要遵循明确的行为契约。
- 坚持 AAA 结构:Arrange(准备输入/模拟依赖)→ Act(调用被测函数)→ Assert(断言结果),不混写
- 所有外部依赖(
fetch、localStorage、第三方库)必须显式 mock,不走真实调用(用vi.mock()或jest.mock()) - 异步测试必须显式等待:用
async/await或返回 Promise,禁止在回调里写expect而不 return - 避免在测试中使用
setTimeout等不可控延时;需测定时逻辑时,用vi.advanceTimersByTime()或jest.runAllTimers()
断言与可维护性兼顾
断言是测试的“判决书”,既要准,也要让人一眼看懂错在哪。
- 优先使用语义化匹配器:
toBe()判等值,toEqual()深比较对象,toThrow()验证异常,不直接用===或== - 每个
test()块只设一个主断言(核心输出),最多加 1–2 个辅助断言(如 mock 函数调用次数mockFn.mock.calls.length) - 边界场景必须覆盖:空值、
null、undefined、非法类型、极值、错误响应——这些不是“额外工作”,而是防止线上崩溃的关键防线 - 不测私有实现细节(如内部变量、未导出的辅助函数),只测公开 API 行为;若某段逻辑复杂且独立,应先抽成导出函数再测
工具链与工程化约束
靠人盯不如靠机制,把规范固化到开发流程中。
- 在
vitest.config.ts或jest.config.js中启用 globals: true,确保test、describe、beforeEach全局可用,避免ReferenceError - 配合 ESLint 添加测试专属规则,如禁止未使用的变量(
no-unused-vars)、强制 expect 有匹配器(jest/valid-expect) - 通过 husky + lint-staged 在
git commit前自动运行测试,失败则阻断提交 - CI 流程中要求测试覆盖率达标(如函数覆盖率 ≥ 80%),但不盲目追求 100%,重质量而非数字











