import { UserService } from '../user.service'; import { DataSource, Repository } from 'typeorm'; import { UserEntity as User } from '../user.entity'; import { Role } from '../role.entity'; import * as bcrypt from 'bcrypt'; // Mock TypeORM 数据源和仓库 jest.mock('typeorm', () => ({ DataSource: jest.fn().mockImplementation(() => ({ getRepository: jest.fn() })), Repository: jest.fn() })); // Mock bcrypt jest.mock('bcrypt', () => ({ hash: jest.fn().mockResolvedValue('hashed_password'), compare: jest.fn().mockResolvedValue(true) })); describe('UserService', () => { let userService: UserService; let mockDataSource: jest.Mocked; let mockUserRepository: jest.Mocked>; let mockRoleRepository: jest.Mocked>; beforeEach(() => { // 创建模拟的仓库实例 mockUserRepository = { create: jest.fn(), save: jest.fn(), findOne: jest.fn(), update: jest.fn(), delete: jest.fn(), createQueryBuilder: jest.fn(), find: jest.fn(), findByIds: jest.fn() } as any; mockRoleRepository = { findByIds: jest.fn() } as any; // 创建模拟的数据源 mockDataSource = { getRepository: jest.fn() } as any; // 设置数据源返回模拟的仓库 mockDataSource.getRepository .mockReturnValueOnce(mockUserRepository) .mockReturnValueOnce(mockRoleRepository); userService = new UserService(mockDataSource); }); afterEach(() => { jest.clearAllMocks(); }); describe('createUser', () => { it('应该成功创建用户并哈希密码', async () => { const userData = { username: 'testuser', password: 'password123', email: 'test@example.com' }; const mockUser = { id: 1, ...userData, password: 'hashed_password' } as User; mockUserRepository.create.mockReturnValue(mockUser); mockUserRepository.save.mockResolvedValue(mockUser); const result = await userService.createUser(userData); expect(bcrypt.hash).toHaveBeenCalledWith('password123', 10); expect(mockUserRepository.create).toHaveBeenCalledWith({ ...userData, password: 'hashed_password' }); expect(mockUserRepository.save).toHaveBeenCalledWith(mockUser); expect(result).toEqual(mockUser); }); it('应该在创建用户失败时抛出错误', async () => { const userData = { username: 'testuser', password: 'password123' }; const error = new Error('Database error'); mockUserRepository.create.mockImplementation(() => { throw error; }); await expect(userService.createUser(userData)).rejects.toThrow('Failed to create user'); }); }); describe('getUserById', () => { it('应该通过ID成功获取用户', async () => { const mockUser = { id: 1, username: 'testuser' } as User; mockUserRepository.findOne.mockResolvedValue(mockUser); const result = await userService.getUserById(1); expect(mockUserRepository.findOne).toHaveBeenCalledWith({ where: { id: 1 }, relations: ['roles'] }); expect(result).toEqual(mockUser); }); it('应该在用户不存在时返回null', async () => { mockUserRepository.findOne.mockResolvedValue(null); const result = await userService.getUserById(999); expect(result).toBeNull(); }); }); describe('getUsersWithPagination', () => { it('应该成功获取分页用户列表', async () => { const mockUsers = [{ id: 1 }, { id: 2 }] as User[]; const total = 2; const mockQueryBuilder = { leftJoinAndSelect: jest.fn().mockReturnThis(), skip: jest.fn().mockReturnThis(), take: jest.fn().mockReturnThis(), where: jest.fn().mockReturnThis(), getManyAndCount: jest.fn().mockResolvedValue([mockUsers, total]) }; mockUserRepository.createQueryBuilder.mockReturnValue(mockQueryBuilder as any); const result = await userService.getUsersWithPagination({ page: 1, pageSize: 10 }); expect(mockQueryBuilder.skip).toHaveBeenCalledWith(0); expect(mockQueryBuilder.take).toHaveBeenCalledWith(10); expect(result).toEqual([mockUsers, total]); }); it('应该支持关键词搜索', async () => { const mockQueryBuilder = { leftJoinAndSelect: jest.fn().mockReturnThis(), skip: jest.fn().mockReturnThis(), take: jest.fn().mockReturnThis(), where: jest.fn().mockReturnThis(), getManyAndCount: jest.fn().mockResolvedValue([[], 0]) }; mockUserRepository.createQueryBuilder.mockReturnValue(mockQueryBuilder as any); await userService.getUsersWithPagination({ page: 1, pageSize: 10, keyword: 'test' }); expect(mockQueryBuilder.where).toHaveBeenCalledWith( 'user.username LIKE :keyword OR user.nickname LIKE :keyword OR user.phone LIKE :keyword', { keyword: '%test%' } ); }); }); describe('verifyPassword', () => { it('应该验证密码正确', async () => { const user = { password: 'hashed_password' } as User; const result = await userService.verifyPassword(user, 'password123'); expect(bcrypt.compare).toHaveBeenCalledWith('password123', 'hashed_password'); expect(result).toBe(true); }); it('应该验证密码错误', async () => { (bcrypt.compare as jest.Mock).mockResolvedValueOnce(false); const user = { password: 'hashed_password' } as User; const result = await userService.verifyPassword(user, 'wrong_password'); expect(result).toBe(false); }); }); });