import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest'; import { DataSource } from 'typeorm'; import { MiniAuthService } from '../../src/services'; import { UserEntity } from '@d8d/user-module'; // Mock 依赖 vi.mock('@d8d/shared-utils', async (importOriginal) => { const actual = await importOriginal() as any; return { ...actual, JWTUtil: { generateToken: vi.fn().mockReturnValue('mock-jwt-token') }, redisUtil: { setSessionKey: vi.fn().mockResolvedValue(undefined), getSessionKey: vi.fn().mockResolvedValue('mock-session-key') } }; }); vi.mock('@d8d/file-module', () => ({ FileService: vi.fn().mockImplementation(() => ({ downloadAndSaveFromUrl: vi.fn().mockResolvedValue({ file: { id: 1 } }) })) })); describe('MiniAuthService', () => { let miniAuthService: MiniAuthService; let mockDataSource: DataSource; let mockUserRepository: any; beforeEach(() => { // Mock DataSource mockUserRepository = { findOne: vi.fn(), create: vi.fn(), save: vi.fn() }; mockDataSource = { getRepository: vi.fn().mockReturnValue(mockUserRepository) } as any; miniAuthService = new MiniAuthService(mockDataSource); }); afterEach(() => { vi.clearAllMocks(); }); describe('decryptPhoneNumber', () => { it('应该成功解密有效的手机号数据', async () => { // 模拟有效的加密数据、IV和sessionKey const encryptedData = 'valid_encrypted_data'; const iv = 'valid_iv'; const sessionKey = 'valid_session_key'; // 这里我们模拟一个成功的解密过程 // 在实际测试中,可能需要更复杂的模拟 const result = await miniAuthService.decryptPhoneNumber(encryptedData, iv, sessionKey); // 由于我们无法真正模拟 crypto 模块,这里主要测试方法调用 expect(result).toBeDefined(); }); it('应该拒绝空的加密数据', async () => { const encryptedData = ''; const iv = 'valid_iv'; const sessionKey = 'valid_session_key'; await expect(miniAuthService.decryptPhoneNumber(encryptedData, iv, sessionKey)) .rejects.toMatchObject({ code: 400, message: '加密数据或初始向量不能为空' }); }); it('应该拒绝空的初始向量', async () => { const encryptedData = 'valid_encrypted_data'; const iv = ''; const sessionKey = 'valid_session_key'; await expect(miniAuthService.decryptPhoneNumber(encryptedData, iv, sessionKey)) .rejects.toMatchObject({ code: 400, message: '加密数据或初始向量不能为空' }); }); it('应该拒绝空的sessionKey', async () => { const encryptedData = 'valid_encrypted_data'; const iv = 'valid_iv'; const sessionKey = ''; await expect(miniAuthService.decryptPhoneNumber(encryptedData, iv, sessionKey)) .rejects.toMatchObject({ code: 400, message: '加密数据或初始向量不能为空' }); }); it('应该处理解密失败的情况', async () => { // 模拟无效的加密数据 const encryptedData = 'invalid_encrypted_data'; const iv = 'invalid_iv'; const sessionKey = 'invalid_session_key'; // 由于我们无法真正模拟 crypto 模块,这里主要测试错误处理 await expect(miniAuthService.decryptPhoneNumber(encryptedData, iv, sessionKey)) .rejects.toMatchObject({ code: 400 }); }); }); describe('miniLogin', () => { it('应该成功处理小程序登录', async () => { // Mock 微信API响应 const mockOpenidInfo = { openid: 'test_openid', session_key: 'test_session_key' }; // Mock 用户数据 const mockUser = { id: 1, username: 'wx_user', openid: 'test_openid' } as UserEntity; // Mock 方法 vi.spyOn(miniAuthService as any, 'getOpenIdByCode').mockResolvedValue(mockOpenidInfo); mockUserRepository.findOne.mockResolvedValue(mockUser); const result = await miniAuthService.miniLogin('test_code'); expect(result).toHaveProperty('token'); expect(result).toHaveProperty('user'); expect(result).toHaveProperty('isNewUser'); expect(result.token).toBe('mock-jwt-token'); expect(result.user).toEqual(mockUser); expect(result.isNewUser).toBe(false); }); it('应该为新用户创建账户', async () => { // Mock 微信API响应 const mockOpenidInfo = { openid: 'new_user_openid', session_key: 'test_session_key' }; // Mock 新用户数据 const mockNewUser = { id: 2, username: 'wx_new_user', openid: 'new_user_openid' } as UserEntity; // Mock 方法 vi.spyOn(miniAuthService as any, 'getOpenIdByCode').mockResolvedValue(mockOpenidInfo); vi.spyOn(miniAuthService as any, 'createMiniUser').mockResolvedValue(mockNewUser); mockUserRepository.findOne.mockResolvedValue(null); const result = await miniAuthService.miniLogin('test_code'); expect(result.isNewUser).toBe(true); expect(result.user).toEqual(mockNewUser); }); }); describe('updateUserProfile', () => { it('应该成功更新用户资料', async () => { const mockUser = { id: 1, nickname: 'old_nickname', avatarFileId: null } as UserEntity; mockUserRepository.findOne.mockResolvedValue(mockUser); mockUserRepository.save.mockResolvedValue({ ...mockUser, nickname: 'new_nickname' }); const result = await miniAuthService.updateUserProfile(1, { nickname: 'new_nickname' }); expect(result.nickname).toBe('new_nickname'); expect(mockUserRepository.save).toHaveBeenCalled(); }); it('应该处理用户不存在的情况', async () => { mockUserRepository.findOne.mockResolvedValue(null); await expect(miniAuthService.updateUserProfile(999, { nickname: 'test' })) .rejects.toThrow('用户不存在'); }); }); });