/** * RegisterService 单元测试 * * 功能描述: * - 测试用户注册相关的业务逻辑 * - 验证邮箱验证功能 * - 测试Zulip账号集成 * * 最近修改: * - 2026-01-15: 代码规范优化 - 清理未使用的变量apiKeySecurityService (修改者: moyin) * - 2026-01-12: 代码分离 - 从login.service.spec.ts中分离注册相关测试 * * @author moyin * @version 1.0.1 * @since 2026-01-12 * @lastModified 2026-01-15 */ import { Test, TestingModule } from '@nestjs/testing'; import { RegisterService } from './register.service'; import { LoginCoreService } from '../../core/login_core/login_core.service'; import { ZulipAccountService } from '../../core/zulip_core/services/zulip_account.service'; import { ApiKeySecurityService } from '../../core/zulip_core/services/api_key_security.service'; describe('RegisterService', () => { let service: RegisterService; let loginCoreService: jest.Mocked; let zulipAccountService: jest.Mocked; const mockUser = { id: BigInt(1), username: 'testuser', nickname: 'Test User', email: 'test@example.com', phone: null, avatar_url: null, role: 1, created_at: new Date(), updated_at: new Date(), password_hash: 'hashed_password', github_id: null, is_active: true, last_login_at: null, email_verified: false, phone_verified: false, }; beforeEach(async () => { const mockLoginCoreService = { register: jest.fn(), sendEmailVerification: jest.fn(), verifyEmailCode: jest.fn(), resendEmailVerification: jest.fn(), deleteUser: jest.fn(), generateTokenPair: jest.fn(), }; const mockZulipAccountService = { initializeAdminClient: jest.fn(), createZulipAccount: jest.fn(), linkGameAccount: jest.fn(), }; const mockZulipAccountsService = { findByGameUserId: jest.fn(), create: jest.fn(), deleteByGameUserId: jest.fn(), }; const mockApiKeySecurityService = { storeApiKey: jest.fn(), }; const module: TestingModule = await Test.createTestingModule({ providers: [ RegisterService, { provide: LoginCoreService, useValue: mockLoginCoreService, }, { provide: ZulipAccountService, useValue: mockZulipAccountService, }, { provide: 'ZulipAccountsService', useValue: mockZulipAccountsService, }, { provide: ApiKeySecurityService, useValue: mockApiKeySecurityService, }, ], }).compile(); service = module.get(RegisterService); loginCoreService = module.get(LoginCoreService); zulipAccountService = module.get(ZulipAccountService); // 设置默认的mock返回值 const mockTokenPair = { access_token: 'mock_access_token', refresh_token: 'mock_refresh_token', expires_in: 3600, token_type: 'Bearer', }; loginCoreService.generateTokenPair.mockResolvedValue(mockTokenPair); zulipAccountService.initializeAdminClient.mockResolvedValue(true); zulipAccountService.createZulipAccount.mockResolvedValue({ success: true, userId: 123, email: 'test@example.com', apiKey: 'mock_api_key', isExistingUser: false }); }); it('should be defined', () => { expect(service).toBeDefined(); }); describe('register', () => { it('should handle user registration successfully', async () => { loginCoreService.register.mockResolvedValue({ user: mockUser, isNewUser: true }); const result = await service.register({ username: 'testuser', password: 'password123', nickname: 'Test User', email: 'test@example.com' }); expect(result.success).toBe(true); expect(result.data?.user.username).toBe('testuser'); expect(result.data?.is_new_user).toBe(true); expect(loginCoreService.register).toHaveBeenCalled(); }); it('should handle registration failure', async () => { loginCoreService.register.mockRejectedValue(new Error('Registration failed')); const result = await service.register({ username: 'testuser', password: 'password123', nickname: 'Test User', email: 'test@example.com' }); expect(result.success).toBe(false); expect(result.message).toContain('Registration failed'); }); }); describe('sendEmailVerification', () => { it('should handle sendEmailVerification in test mode', async () => { loginCoreService.sendEmailVerification.mockResolvedValue({ code: '123456', isTestMode: true }); const result = await service.sendEmailVerification('test@example.com'); expect(result.success).toBe(false); // Test mode returns false expect(result.data?.verification_code).toBe('123456'); expect(result.data?.is_test_mode).toBe(true); expect(loginCoreService.sendEmailVerification).toHaveBeenCalledWith('test@example.com'); }); it('should handle sendEmailVerification in production mode', async () => { loginCoreService.sendEmailVerification.mockResolvedValue({ code: '123456', isTestMode: false }); const result = await service.sendEmailVerification('test@example.com'); expect(result.success).toBe(true); expect(result.data?.is_test_mode).toBe(false); expect(loginCoreService.sendEmailVerification).toHaveBeenCalledWith('test@example.com'); }); }); describe('verifyEmailCode', () => { it('should handle verifyEmailCode successfully', async () => { loginCoreService.verifyEmailCode.mockResolvedValue(true); const result = await service.verifyEmailCode('test@example.com', '123456'); expect(result.success).toBe(true); expect(result.message).toBe('邮箱验证成功'); expect(loginCoreService.verifyEmailCode).toHaveBeenCalledWith('test@example.com', '123456'); }); it('should handle invalid verification code', async () => { loginCoreService.verifyEmailCode.mockResolvedValue(false); const result = await service.verifyEmailCode('test@example.com', '123456'); expect(result.success).toBe(false); expect(result.message).toBe('验证码错误'); }); }); describe('resendEmailVerification', () => { it('should handle resendEmailVerification successfully', async () => { loginCoreService.resendEmailVerification.mockResolvedValue({ code: '654321', isTestMode: false }); const result = await service.resendEmailVerification('test@example.com'); expect(result.success).toBe(true); expect(result.data?.is_test_mode).toBe(false); expect(loginCoreService.resendEmailVerification).toHaveBeenCalledWith('test@example.com'); }); }); });