| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- 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<DataSource>;
- let mockUserRepository: jest.Mocked<Repository<User>>;
- let mockRoleRepository: jest.Mocked<Repository<Role>>;
- 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);
- });
- });
- });
|