- 重构项目结构:controllers/services -> modules模块化组织 - 新增Drizzle ORM集成和数据库schema定义 - 添加完整的开发规范文档(.cursor/rules/) - 重新组织插件结构为子目录方式 - 新增用户模块和示例代码 - 更新类型定义并移除试验性代码 - 添加API文档和JWT使用示例 关联任务计划文档
188 lines
6.8 KiB
TypeScript
188 lines
6.8 KiB
TypeScript
/**
|
||
* @file 样例接口测试用例
|
||
* @author hotok
|
||
* @date 2025-06-29
|
||
* @lastEditor hotok
|
||
* @lastEditTime 2025-06-29
|
||
* @description 样例接口的完整测试用例,覆盖正常、异常、边界场景
|
||
*/
|
||
|
||
import { describe, it, expect, beforeAll } from 'vitest';
|
||
import { Elysia } from 'elysia';
|
||
import { sampleController } from './example.controller';
|
||
import { jwtPlugin } from '@/plugins/jwt/jwt.plugins';
|
||
|
||
// 创建测试应用实例
|
||
const app = new Elysia()
|
||
.use(jwtPlugin)
|
||
.use(sampleController);
|
||
|
||
// 测试用的JWT Token(需要根据实际情况生成)
|
||
let testToken = '';
|
||
|
||
describe('样例接口测试', () => {
|
||
beforeAll(async () => {
|
||
// 在实际测试中,这里应该通过登录接口获取有效token
|
||
// 这里为了演示,假设我们有一个有效的token
|
||
// 创建临时的JWT实例来生成测试token
|
||
const tempApp = new Elysia().use(jwtPlugin);
|
||
const context = { jwt: tempApp.derive().jwt };
|
||
|
||
testToken = await context.jwt.sign({
|
||
userId: 1,
|
||
username: 'admin',
|
||
iat: Math.floor(Date.now() / 1000),
|
||
});
|
||
});
|
||
|
||
describe('GET /api/sample/user/:username', () => {
|
||
it('应该成功查询存在的用户', async () => {
|
||
const res = await app.fetch(
|
||
new Request('http://localhost/sample/user/admin', {
|
||
method: 'GET',
|
||
headers: {
|
||
'Authorization': `Bearer ${testToken}`,
|
||
},
|
||
}),
|
||
);
|
||
|
||
const body = (await res.json()) as any;
|
||
console.log('成功查询响应:', body);
|
||
|
||
expect(res.status).toBe(200);
|
||
expect(body.code).toBe(0);
|
||
expect(body.message).toBe('查询用户成功');
|
||
expect(body.data).toBeDefined();
|
||
expect(typeof body.data.id).toBe('number');
|
||
expect(typeof body.data.username).toBe('string');
|
||
expect(typeof body.data.email).toBe('string');
|
||
});
|
||
|
||
it('用户名过短应返回422', async () => {
|
||
const res = await app.fetch(
|
||
new Request('http://localhost/sample/user/a', {
|
||
method: 'GET',
|
||
headers: {
|
||
'Authorization': `Bearer ${testToken}`,
|
||
},
|
||
}),
|
||
);
|
||
|
||
const body = (await res.json()) as any;
|
||
console.log('用户名过短响应:', body);
|
||
|
||
expect(res.status).toBe(422);
|
||
expect(body.code).toBe(422);
|
||
expect(body.message).toMatch(/用户名/);
|
||
});
|
||
|
||
it('用户名过长应返回422', async () => {
|
||
const res = await app.fetch(
|
||
new Request('http://localhost/sample/user/' + 'a'.repeat(51), {
|
||
method: 'GET',
|
||
headers: {
|
||
'Authorization': `Bearer ${testToken}`,
|
||
},
|
||
}),
|
||
);
|
||
|
||
const body = (await res.json()) as any;
|
||
console.log('用户名过长响应:', body);
|
||
|
||
expect(res.status).toBe(422);
|
||
expect(body.code).toBe(422);
|
||
expect(body.message).toMatch(/用户名/);
|
||
});
|
||
|
||
it('用户不存在应返回400', async () => {
|
||
const res = await app.fetch(
|
||
new Request('http://localhost/sample/user/nonexistentuser12345', {
|
||
method: 'GET',
|
||
headers: {
|
||
'Authorization': `Bearer ${testToken}`,
|
||
},
|
||
}),
|
||
);
|
||
|
||
const body = (await res.json()) as any;
|
||
console.log('用户不存在响应:', body);
|
||
|
||
expect(res.status).toBe(400);
|
||
expect(body.code).toBe(400);
|
||
expect(body.message).toBe('用户不存在');
|
||
expect(body.data).toBeNull();
|
||
});
|
||
|
||
it('缺少Authorization头应返回401', async () => {
|
||
const res = await app.fetch(
|
||
new Request('http://localhost/sample/user/admin', {
|
||
method: 'GET',
|
||
}),
|
||
);
|
||
|
||
const body = (await res.json()) as any;
|
||
console.log('缺少Authorization响应:', body);
|
||
|
||
expect(res.status).toBe(401);
|
||
expect(body.code).toBe(401);
|
||
expect(body.message).toMatch(/Token|认证|授权/);
|
||
});
|
||
|
||
it('无效Token应返回401', async () => {
|
||
const res = await app.fetch(
|
||
new Request('http://localhost/sample/user/admin', {
|
||
method: 'GET',
|
||
headers: {
|
||
Authorization: 'Bearer invalid_token_here',
|
||
},
|
||
}),
|
||
);
|
||
|
||
const body = (await res.json()) as any;
|
||
console.log('无效Token响应:', body);
|
||
|
||
expect(res.status).toBe(401);
|
||
expect(body.code).toBe(401);
|
||
expect(body.message).toMatch(/Token|认证|授权/);
|
||
});
|
||
|
||
it('错误的Authorization格式应返回401', async () => {
|
||
const res = await app.fetch(
|
||
new Request('http://localhost/sample/user/admin', {
|
||
method: 'GET',
|
||
headers: {
|
||
Authorization: 'InvalidFormat token',
|
||
},
|
||
}),
|
||
);
|
||
|
||
const body = (await res.json()) as any;
|
||
console.log('错误Authorization格式响应:', body);
|
||
|
||
expect(res.status).toBe(401);
|
||
expect(body.code).toBe(401);
|
||
expect(body.message).toMatch(/Token|认证|授权/);
|
||
});
|
||
});
|
||
|
||
describe('GET /api/sample/health', () => {
|
||
it('应该返回模块健康状态', async () => {
|
||
const res = await app.fetch(
|
||
new Request('http://localhost/sample/health', {
|
||
method: 'GET',
|
||
}),
|
||
);
|
||
|
||
const body = (await res.json()) as any;
|
||
console.log('健康检查响应:', body);
|
||
|
||
expect(res.status).toBe(200);
|
||
expect(body.code).toBe(0);
|
||
expect(body.message).toBe('样例模块运行正常');
|
||
expect(body.data).toBeDefined();
|
||
expect(body.data.module).toBe('sample');
|
||
expect(body.data.status).toBe('healthy');
|
||
expect(typeof body.data.timestamp).toBe('string');
|
||
});
|
||
});
|
||
});
|