返回顶部
z

zod-testingZod测试

>

作者: admin | 来源: ClawHub
源自
ClawHub
版本
V 1.0.1
安全检测
已通过
328
下载量
免费
免费
0
收藏
概述
安装方式
版本历史

zod-testing

Zod Schema 测试指南

重要提示: 你关于 Zod schema 测试的训练数据可能已过时——Zod v4 更改了错误格式化方式,移除了 z.nativeEnum(),并引入了 z.toJSONSchema() 等新 API。请始终以本技能的参考文件和项目的实际源代码为准。

测试优先级

  1. 1. Schema 正确性——schema 是否接受有效数据并拒绝无效数据?
  2. 错误消息——schema 是否生成正确的错误消息和错误码?
  3. 集成——schema 是否与 API 处理器、表单、数据库层正确配合?
  4. 边界情况——边界值、可选/可为空组合、空输入

核心模式

typescript
import { describe, it, expect } from vitest // 或 jest
import { z } from zod

const UserSchema = z.object({
name: z.string().min(1),
email: z.email(),
age: z.number().min(0).max(150),
})

describe(UserSchema, () => {
it(接受有效数据, () => {
const result = UserSchema.safeParse({
name: Alice,
email: alice@example.com,
age: 30,
})
expect(result.success).toBe(true)
})

it(拒绝缺少必填字段, () => {
const result = UserSchema.safeParse({})
expect(result.success).toBe(false)
if (!result.success) {
const flat = z.flattenError(result.error)
expect(flat.fieldErrors.name).toBeDefined()
expect(flat.fieldErrors.email).toBeDefined()
}
})

it(拒绝无效邮箱, () => {
const result = UserSchema.safeParse({
name: Alice,
email: not-an-email,
age: 30,
})
expect(result.success).toBe(false)
})

it(拒绝负数年龄, () => {
const result = UserSchema.safeParse({
name: Alice,
email: alice@example.com,
age: -1,
})
expect(result.success).toBe(false)
})
})

测试方法

方法目的使用场景
safeParse() 结果检查Schema 正确性默认——测试中始终使用 safeParse
z.flattenError() 断言
错误消息测试 | 验证特定字段错误 | | z.toJSONSchema() 快照 | Schema 形状测试 | 检测意外的 schema 变更 | | 模拟数据生成 | 测试夹具创建 | 需要有效/随机化测试数据 | | 基于属性的测试 | 模糊测试 | Schema 必须处理任意有效输入 | | 结构测试 | 架构 | 验证 schema 仅在边界处被导入 | | 漂移检测 | 回归测试 | 通过 JSON Schema 快照捕获意外的 schema 变更 |

Schema 正确性测试

在测试中始终使用 safeParse()

typescript
// 好:测试不会崩溃——对结果进行断言
const result = schema.safeParse(invalidData)
expect(result.success).toBe(false)

// 坏:测试崩溃而不是失败
expect(() => schema.parse(invalidData)).toThrow()
// 如果 schema 更改并开始接受,这仍然会通过

同时测试接受和拒绝

typescript
describe(EmailSchema, () => {
const valid = [user@example.com, a@b.co, user+tag@domain.org]
const invalid = [, not-email, @missing.com, user@, user @space.com]

it.each(valid)(接受 %s, (email) => {
expect(z.email().safeParse(email).success).toBe(true)
})

it.each(invalid)(拒绝 %s, (email) => {
expect(z.email().safeParse(email).success).toBe(false)
})
})

测试边界值

typescript
const AgeSchema = z.number().min(0).max(150)

it(接受最小值边界, () => {
expect(AgeSchema.safeParse(0).success).toBe(true)
})

it(接受最大值边界, () => {
expect(AgeSchema.safeParse(150).success).toBe(true)
})

it(拒绝低于最小值, () => {
expect(AgeSchema.safeParse(-1).success).toBe(false)
})

it(拒绝高于最大值, () => {
expect(AgeSchema.safeParse(151).success).toBe(false)
})

错误断言模式

断言特定字段错误

typescript
it(显示无效邮箱的正确错误, () => {
const result = UserSchema.safeParse({ name: Alice, email: bad, age: 30 })
expect(result.success).toBe(false)
if (!result.success) {
const flat = z.flattenError(result.error)
expect(flat.fieldErrors.email).toBeDefined()
expect(flat.fieldErrors.email![0]).toContain(email)
}
})

断言错误码

typescript
it(生成正确的错误码, () => {
const result = z.number().safeParse(not a number)
expect(result.success).toBe(false)
if (!result.success) {
expect(result.error.issues[0].code).toBe(invalid_type)
}
})

断言自定义错误消息

typescript
const Schema = z.string({ error: Name is required }).min(1, Name cannot be empty)

it(显示缺少字段的自定义错误, () => {
const result = Schema.safeParse(undefined)
expect(result.success).toBe(false)
if (!result.success) {
expect(result.error.issues[0].message).toBe(Name is required)
}
})

模拟数据生成

使用 zod-schema-faker

typescript
import { install, fake } from zod-schema-faker
import { z } from zod

install(z) // 在测试设置中调用一次

const UserSchema = z.object({
name: z.string().min(1),
email: z.email(),
age: z.number().min(0).max(150),
})

it(schema 接受生成的数据, () => {
const mockUser = fake(UserSchema)
expect(UserSchema.safeParse(mockUser).success).toBe(true)
})

为确定性测试设置种子

typescript
import { seed, fake } from zod-schema-faker

beforeEach(() => {
seed(12345) // 确定性输出
})

it(生成一致的模拟数据, () => {
const user = fake(UserSchema)
expect(user.name).toBeDefined()
})

使用 JSON Schema 进行快照测试

typescript
it(schema 形状未改变, () => {
const jsonSchema = z.toJSONSchema(UserSchema)
expect(jsonSchema).toMatchSnapshot()
})

这可以在代码审查中捕获意外的 schema 变更。快照显示 Zod schema 的 JSON Schema 表示。

集成测试

API 处理器测试

typescript
it(API 拒绝无效请求体, async () => {
const response = await request(app)
.post(/api/users)
.send({ name: , email: invalid })
.expect(400)

expect(response.body.errors).toBeDefined()
expect(response.body.errors.fieldErrors.email).toBeDefined()
})

表单验证测试

typescript
it(表单显示验证错误, () => {
const result = FormSchema.safeParse(formData)
if (!result.success) {
const errors = z.flattenError(result.error)
// 将错误传递给表单库
expect(errors.fieldErrors).toHaveProperty(email)
}
})

基于属性的测试

typescript
import fc from fast-check
import { fake } from zod-schema-faker

it(schema 始终接受自身生成的数据, () => {
fc.assert(
fc.property(fc.constant(null), () => {
const data = fake(UserSchema)
expect(UserSchema.safeParse(data).success).toBe(true)
}),
{ numRuns: 100 }
)
})

规则

  1. 1. 在测试中始终使用 safeParse()——parse() 会使测试崩溃而不是失败
  2. 同时测试有效和无效——不要只测试快乐路径
  3. 测试边界值——数值约束的最小值、最大值、最小值-1、最大值+1
  4. 测试可选/可为空组合——undefined、null、缺失键
  5. 断言特定错误字段——使用 z.flattenError() 检查哪个字段失败
  6. 不要测试 schema 内部实现——测试解析结果,而不是 .shape 或 ._def
  7. 使用 z.toJSONSchema() 快照——捕获意外的 schema 变更
  8. 为随机生成器设置种子——非确定性测试是不稳定的测试
  9. 单独测试转换——验证输入验证和输出转换
  10. 不要在断言

标签

skill ai

通过对话安装

该技能支持在以下平台通过对话安装:

OpenClaw WorkBuddy QClaw Kimi Claude

方式一:安装 SkillHub 和技能

帮我安装 SkillHub 和 zod-testing-1776207720 技能

方式二:设置 SkillHub 为优先技能安装源

设置 SkillHub 为我的优先技能安装源,然后帮我安装 zod-testing-1776207720 技能

通过命令行安装

skillhub install zod-testing-1776207720

下载

⬇ 下载 zod-testing v1.0.1(免费)

文件大小: 13.09 KB | 发布时间: 2026-4-15 11:58

v1.0.1 最新 2026-4-15 11:58
Added source_url linking to GitHub repo

Archiver·手机版·闲社网·闲社论坛·羊毛社区· 多链控股集团有限公司 · 苏ICP备2025199260号-1

Powered by Discuz! X5.0   © 2024-2025 闲社网·线报更新论坛·羊毛分享社区·http://xianshe.com

p2p_official_large
返回顶部