import { OpenAPIHono } from '@hono/zod-openapi'; import { UserService } from '../../../modules/users/user.service'; import { DataSource } from 'typeorm'; import { createTestServer } from '../../../../test/test-utils'; // Mock 用户服务 jest.mock('../../../modules/users/user.service'); // Mock 数据源 jest.mock('../../../data-source', () => ({ AppDataSource: { getRepository: jest.fn() } })); describe('GET /users API', () => { let app: OpenAPIHono; let mockUserService: jest.Mocked; beforeEach(() => { jest.clearAllMocks(); // 创建模拟的用户服务 mockUserService = { getUsersWithPagination: jest.fn() } as any; // Mock UserService 构造函数 (UserService as jest.MockedClass).mockImplementation(() => mockUserService); // 动态导入以避免缓存问题 jest.isolateModules(async () => { const module = await import('../get'); app = module.default; }); }); describe('参数验证', () => { it('应该验证页码必须为正整数', async () => { const server = createTestServer(app); const response = await server.get('/users?page=0'); expect(response.status).toBe(400); expect(await response.json()).toMatchObject({ code: 400, message: '参数错误' }); }); it('应该验证每页数量必须为正整数', async () => { const server = createTestServer(app); const response = await server.get('/users?pageSize=0'); expect(response.status).toBe(400); expect(await response.json()).toMatchObject({ code: 400, message: '参数错误' }); }); it('应该接受有效的分页参数', async () => { const mockUsers = [{ id: 1, username: 'testuser' }]; const total = 1; mockUserService.getUsersWithPagination.mockResolvedValue([mockUsers as any, total]); const server = createTestServer(app); const response = await server.get('/users?page=1&pageSize=10'); expect(response.status).toBe(200); expect(mockUserService.getUsersWithPagination).toHaveBeenCalledWith({ page: 1, pageSize: 10, keyword: undefined }); }); }); describe('成功响应', () => { it('应该返回用户列表和分页信息', async () => { const mockUsers = [ { id: 1, username: 'user1', email: 'user1@example.com' }, { id: 2, username: 'user2', email: 'user2@example.com' } ]; const total = 2; mockUserService.getUsersWithPagination.mockResolvedValue([mockUsers as any, total]); const server = createTestServer(app); const response = await server.get('/users?page=1&pageSize=10'); expect(response.status).toBe(200); expect(await response.json()).toEqual({ data: mockUsers, pagination: { total: 2, current: 1, pageSize: 10 } }); }); it('应该支持关键词搜索', async () => { const mockUsers = [{ id: 1, username: 'admin' }]; const total = 1; mockUserService.getUsersWithPagination.mockResolvedValue([mockUsers as any, total]); const server = createTestServer(app); const response = await server.get('/users?page=1&pageSize=10&keyword=admin'); expect(response.status).toBe(200); expect(mockUserService.getUsersWithPagination).toHaveBeenCalledWith({ page: 1, pageSize: 10, keyword: 'admin' }); }); }); describe('错误处理', () => { it('应该在服务抛出错误时返回500错误', async () => { mockUserService.getUsersWithPagination.mockRejectedValue(new Error('Database error')); const server = createTestServer(app); const response = await server.get('/users?page=1&pageSize=10'); expect(response.status).toBe(500); expect(await response.json()).toMatchObject({ code: 500, message: 'Database error' }); }); it('应该在未知错误时返回通用错误消息', async () => { mockUserService.getUsersWithPagination.mockRejectedValue('Unknown error'); const server = createTestServer(app); const response = await server.get('/users?page=1&pageSize=10'); expect(response.status).toBe(500); expect(await response.json()).toMatchObject({ code: 500, message: '获取用户列表失败' }); }); }); });