--- description: globs: alwaysApply: true --- # Elysia + Vitest 测试用例编写规范 ## 1. 文件结构与命名 - 每个被测模块应有对应的 `xxx.test.ts` 文件,放在同目录或 `tests/` 下。 - 测试文件需有文件头注释,说明作者、日期、描述等。 ## 2. 测试用例基本格式 - 使用 `describe` 分组,`it`(或 `test`)描述单个场景。 - 每个 `it` 需有明确的行为描述。 ## 3. 参数传递与类型 - 明确传递参数类型,推荐用 TypeBox schema 自动推导类型。 - 测试用例中参数应覆盖正常、异常、边界值。 ## 4. 响应结构与 code 校验 - 断言 HTTP 状态码(如 200、400、401)。 - 断言响应体结构(如 code、message、data),类型可用 `as any` 或 schema 类型断言。 ## 5. 边界与异常测试 - 必须覆盖参数边界(如最短/最长用户名、最短密码等)。 - 必须覆盖异常分支(如缺少参数、token 错误、未授权等)。 ## 6. 类型安全 - 推荐用 TypeBox 的 `Static` 推导类型,或在测试用例中用 `as any` 简化断言。 - 对于复杂响应,可定义类型辅助断言。 ## 7. 断言范围 - 断言应覆盖:HTTP 状态码、响应 code、message、data 字段、关键数据类型。 - 对于 token、id 等动态值,用 `typeof` 或正则断言。 ## 8. 其他建议 - 用 `it.only`/`describe.only` 聚焦调试,提交前移除。 - 用 `console.log` 输出实际响应,便于排查失败。 - 每个接口的正常、异常、边界场景都应有测试覆盖。 ## 9. 示例 ```typescript /** * @file 用户登录接口测试 * @author hotok * @date 2025-06-28 * @lastEditor hotok * @lastEditTime 2025-06-28 * @description 覆盖登录接口的正常、异常、边界场景 */ describe('POST /api/login', () => { it('应登录成功并返回token', async () => { const res = await app.fetch( new Request('http://localhost/api/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: 'admin', password: '123456' }), }), ); const body = (await res.json()) as any; expect(res.status).toBe(200); expect(body.code).toBe(0); expect(typeof body.data.token).toBe('string'); }); it('用户名过短应返回400', async () => { const res = await app.fetch( new Request('http://localhost/api/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: 'a', password: '123456' }), }), ); const body = (await res.json()) as any; expect(res.status).toBe(400); expect(body.code).toBe(400); expect(body.message).toMatch(/用户名长度/); }); it('密码错误应返回400', async () => { const res = await app.fetch( new Request('http://localhost/api/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: 'admin', password: 'wrong' }), }), ); const body = (await res.json()) as any; expect(res.status).toBe(400); expect(body.code).toBe(400); expect(body.message).toBe('用户名或密码错误'); }); }); ```