Files
whale-town-end/src/gateway/zulip/zulip_accounts.controller.spec.ts
moyin ed04b8c92d docs(zulip): 完善Zulip业务模块功能文档
范围: src/business/zulip/README.md
- 补充对外提供的接口章节(14个公共方法)
- 添加使用的项目内部依赖说明(7个依赖)
- 完善核心特性描述(5个特性)
- 添加潜在风险评估(4个风险及缓解措施)
- 优化文档结构和内容完整性
2026-01-15 10:53:04 +08:00

338 lines
10 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Zulip账号管理控制器测试
*
* 功能描述:
* - 测试Zulip账号关联管理功能
* - 验证账号创建和验证逻辑
* - 测试账号状态管理和更新
* - 验证错误处理和异常情况
*
* 测试范围:
* - 账号关联API测试
* - 账号验证功能测试
* - 状态管理测试
* - 错误处理测试
*
* 最近修改:
* - 2026-01-12: 测试修复 - 修正测试方法名称和Mock配置确保与实际控制器方法匹配 (修改者: moyin)
* - 2026-01-12: 代码规范优化 - 创建测试文件确保Zulip账号管理控制器功能的测试覆盖 (修改者: moyin)
*
* @author moyin
* @version 1.1.0
* @since 2026-01-12
* @lastModified 2026-01-12
*/
import { Test, TestingModule } from '@nestjs/testing';
import { HttpException, HttpStatus } from '@nestjs/common';
import { ZulipAccountsController } from './zulip_accounts.controller';
import { JwtAuthGuard } from '../auth/jwt_auth.guard';
import { AppLoggerService } from '../../core/utils/logger/logger.service';
import { ZulipAccountsBusinessService } from '../../business/zulip/services/zulip_accounts_business.service';
describe('ZulipAccountsController', () => {
let controller: ZulipAccountsController;
let zulipAccountsService: jest.Mocked<any>;
beforeEach(async () => {
const mockZulipAccountsService = {
create: jest.fn(),
findMany: jest.fn(),
findById: jest.fn(),
findByGameUserId: jest.fn(),
findByZulipUserId: jest.fn(),
findByZulipEmail: jest.fn(),
update: jest.fn(),
updateByGameUserId: jest.fn(),
delete: jest.fn(),
deleteByGameUserId: jest.fn(),
findAccountsNeedingVerification: jest.fn(),
findErrorAccounts: jest.fn(),
batchUpdateStatus: jest.fn(),
getStatusStatistics: jest.fn(),
verifyAccount: jest.fn(),
existsByEmail: jest.fn(),
existsByZulipUserId: jest.fn(),
};
const module: TestingModule = await Test.createTestingModule({
controllers: [ZulipAccountsController],
providers: [
{ provide: 'ZulipAccountsService', useValue: mockZulipAccountsService },
{ provide: AppLoggerService, useValue: {
info: jest.fn(),
error: jest.fn(),
bindRequest: jest.fn().mockReturnValue({
info: jest.fn(),
error: jest.fn(),
}),
}},
],
})
.overrideGuard(JwtAuthGuard)
.useValue({ canActivate: () => true })
.compile();
controller = module.get<ZulipAccountsController>(ZulipAccountsController);
zulipAccountsService = module.get('ZulipAccountsService');
});
describe('Controller Initialization', () => {
it('should be defined', () => {
expect(controller).toBeDefined();
});
it('should have zulip accounts service dependency', () => {
expect(zulipAccountsService).toBeDefined();
});
});
describe('create', () => {
const validCreateDto = {
gameUserId: 'game123',
zulipUserId: 456,
zulipEmail: 'user@example.com',
zulipFullName: 'Test User',
zulipApiKeyEncrypted: 'encrypted_api_key_123',
status: 'active' as const,
};
it('should create Zulip account successfully', async () => {
// Arrange
const expectedResult = {
id: 'acc123',
gameUserId: validCreateDto.gameUserId,
zulipUserId: validCreateDto.zulipUserId,
zulipEmail: validCreateDto.zulipEmail,
zulipFullName: validCreateDto.zulipFullName,
status: 'active',
retryCount: 0,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
};
zulipAccountsService.create.mockResolvedValue(expectedResult);
// Act
const result = await controller.create({} as any, validCreateDto);
// Assert
expect(result).toEqual(expectedResult);
expect(zulipAccountsService.create).toHaveBeenCalledWith(validCreateDto);
});
it('should handle service errors during account creation', async () => {
// Arrange
zulipAccountsService.create.mockRejectedValue(
new Error('Database error')
);
// Act & Assert
await expect(controller.create({} as any, validCreateDto)).rejects.toThrow();
});
});
describe('findByGameUserId', () => {
const gameUserId = 'game123';
it('should return account information', async () => {
// Arrange
const expectedInfo = {
id: 'acc123',
gameUserId: gameUserId,
zulipUserId: 456,
zulipEmail: 'user@example.com',
status: 'active',
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
};
zulipAccountsService.findByGameUserId.mockResolvedValue(expectedInfo);
// Act
const result = await controller.findByGameUserId(gameUserId, false);
// Assert
expect(result).toEqual(expectedInfo);
expect(zulipAccountsService.findByGameUserId).toHaveBeenCalledWith(gameUserId, false);
});
it('should handle account not found', async () => {
// Arrange
zulipAccountsService.findByGameUserId.mockResolvedValue(null);
// Act
const result = await controller.findByGameUserId(gameUserId, false);
// Assert
expect(result).toBeNull();
});
it('should handle service errors', async () => {
// Arrange
zulipAccountsService.findByGameUserId.mockRejectedValue(
new Error('Database error')
);
// Act & Assert
await expect(controller.findByGameUserId(gameUserId, false)).rejects.toThrow();
});
});
describe('deleteByGameUserId', () => {
const gameUserId = 'game123';
it('should delete account successfully', async () => {
// Arrange
zulipAccountsService.deleteByGameUserId.mockResolvedValue(undefined);
// Act
const result = await controller.deleteByGameUserId(gameUserId);
// Assert
expect(result).toEqual({ success: true, message: '删除成功' });
expect(zulipAccountsService.deleteByGameUserId).toHaveBeenCalledWith(gameUserId);
});
it('should handle account not found during deletion', async () => {
// Arrange
zulipAccountsService.deleteByGameUserId.mockRejectedValue(
new Error('Account not found')
);
// Act & Assert
await expect(controller.deleteByGameUserId(gameUserId)).rejects.toThrow();
});
});
describe('getStatusStatistics', () => {
it('should return account statistics', async () => {
// Arrange
const expectedStats = {
total: 100,
active: 80,
inactive: 15,
suspended: 3,
error: 2,
};
zulipAccountsService.getStatusStatistics.mockResolvedValue(expectedStats);
// Act
const result = await controller.getStatusStatistics({} as any);
// Assert
expect(result).toEqual(expectedStats);
expect(zulipAccountsService.getStatusStatistics).toHaveBeenCalled();
});
it('should handle service errors', async () => {
// Arrange
zulipAccountsService.getStatusStatistics.mockRejectedValue(
new Error('Database error')
);
// Act & Assert
await expect(controller.getStatusStatistics({} as any)).rejects.toThrow();
});
});
describe('verifyAccount', () => {
const verifyDto = { gameUserId: 'game123' };
it('should verify account successfully', async () => {
// Arrange
const validationResult = {
isValid: true,
gameUserId: verifyDto.gameUserId,
zulipUserId: 456,
status: 'active',
lastValidated: new Date().toISOString(),
};
zulipAccountsService.verifyAccount.mockResolvedValue(validationResult);
// Act
const result = await controller.verifyAccount(verifyDto);
// Assert
expect(result).toEqual(validationResult);
expect(zulipAccountsService.verifyAccount).toHaveBeenCalledWith(verifyDto.gameUserId);
});
it('should handle invalid account', async () => {
// Arrange
const validationResult = {
isValid: false,
gameUserId: verifyDto.gameUserId,
error: 'Account suspended',
lastValidated: new Date().toISOString(),
};
zulipAccountsService.verifyAccount.mockResolvedValue(validationResult);
// Act
const result = await controller.verifyAccount(verifyDto);
// Assert
expect(result).toEqual(validationResult);
expect(result.isValid).toBe(false);
});
it('should handle validation errors', async () => {
// Arrange
zulipAccountsService.verifyAccount.mockRejectedValue(
new Error('Validation service error')
);
// Act & Assert
await expect(controller.verifyAccount(verifyDto)).rejects.toThrow();
});
});
describe('checkEmailExists', () => {
const email = 'user@example.com';
it('should check if email exists', async () => {
// Arrange
zulipAccountsService.existsByEmail.mockResolvedValue(false);
// Act
const result = await controller.checkEmailExists(email);
// Assert
expect(result).toEqual({ exists: false, email });
expect(zulipAccountsService.existsByEmail).toHaveBeenCalledWith(email, undefined);
});
it('should handle service errors when checking email', async () => {
// Arrange
zulipAccountsService.existsByEmail.mockRejectedValue(
new Error('Database error')
);
// Act & Assert
await expect(controller.checkEmailExists(email)).rejects.toThrow();
});
});
describe('Error Handling', () => {
it('should handle service unavailable errors', async () => {
// Arrange
zulipAccountsService.findByGameUserId.mockRejectedValue(
new Error('Service unavailable')
);
// Act & Assert
await expect(controller.findByGameUserId('game123', false)).rejects.toThrow();
});
it('should handle malformed request data', async () => {
// Arrange
const malformedDto = { invalid: 'data' };
// Act & Assert
await expect(controller.create({} as any, malformedDto as any)).rejects.toThrow();
});
});
});