使用Jest测试对象集合结构是否有更优的实现方案?
你当前的实现是可以正常工作的,能准确校验返回的每个exercise对象的键集合和预期完全一致,没有多余也没有缺失,属于合理的实现方式,但是存在几个可优化的空间,同时也有更简洁高效的Jest实践可以参考。
现有实现的可优化点
- 空集合场景会直接通过测试,无法校验
listAllExercises有没有正常返回数据 - 用forEach遍历出错时,只会抛出键不匹配的错误,无法直观看到是第几个exercise、对应哪条数据出问题
- 仅校验键的存在性,不会校验对应值的类型是否符合预期,比如
level是不是数字、is_poly_articular是不是布尔值这类问题发现不了
优化方案参考
方案1:原生Jest无额外依赖,优化错误定位和边界校验
不需要引入任何第三方依赖,只对现有写法做小调整就能大幅提升测试体验:
const allExercises = listAllExercises() const REQUIRED_KEYS = [ "name", "execution", "level", "is_poly_articular", "practice", "gender", "body_focus", ] describe("listAllExercises | should return all exercises", () => { // 先校验返回集合非空,避免空数组直接过测 test("should return non-empty exercise list", () => { expect(allExercises).not.toHaveLength(0) }) // 用.each遍历每个exercise作为独立用例,出错直接定位下标 test.each(allExercises)("exercise #%# has correct structure", (exercise) => { // 校验所有必填键都存在 REQUIRED_KEYS.forEach(key => { expect(exercise).toHaveProperty(key) }) // 校验不存在多余的键 expect(Object.keys(exercise)).toHaveLength(REQUIRED_KEYS.length) // 可选:扩展值类型校验,更严谨 expect(typeof exercise.name).toBe('string') expect(typeof exercise.is_poly_articular).toBe('boolean') // 其他字段按需加类型校验 }) })
方案2:用内置匹配器简化写法,支持类型校验
如果不需要严格禁止多余键,只要求所有必填键存在,可直接用expect.objectContaining匹配器,不需要手动遍历键列表:
test.each(allExercises)("exercise #%# has all required keys", (exercise) => { expect(exercise).toEqual(expect.objectContaining({ name: expect.any(String), execution: expect.any(String), level: expect.any(Number), is_poly_articular: expect.any(Boolean), practice: expect.any(String), gender: expect.any(String), body_focus: expect.any(String), })) })
如果需要严格禁止多余键,额外加一行expect(Object.keys(exercise)).toHaveLength(7)即可。
方案3:复杂场景用Zod做结构校验
如果结构校验逻辑复杂、或者需要复用结构定义,推荐引入Zod定义Schema,校验精度更高、错误信息更清晰:
首先定义可复用的结构Schema:
import { z } from 'zod' const ExerciseSchema = z.object({ name: z.string(), execution: z.string(), level: z.enum(['beginner', 'intermediate', 'advanced']), // 支持限定枚举值 is_poly_articular: z.boolean(), practice: z.string(), gender: z.enum(['male', 'female', 'neutral']), body_focus: z.string(), })
测试代码:
test.each(allExercises)("exercise #%# matches structure schema", (exercise) => { const parseResult = ExerciseSchema.safeParse(exercise) // 出错时parseResult.error会返回非常详细的错误信息,精准定位问题字段 expect(parseResult.success).toBe(true) })
内容的提问来源于stack exchange,提问作者Jean-Baptiste THERY
相关产品推荐
相关产品推荐

