Remove merge-requests files from git tracking
This commit is contained in:
195
src/business/zulip/chat.controller.spec.ts
Normal file
195
src/business/zulip/chat.controller.spec.ts
Normal file
@@ -0,0 +1,195 @@
|
||||
/**
|
||||
* 聊天控制器测试
|
||||
*
|
||||
* 功能描述:
|
||||
* - 测试聊天消息发送功能
|
||||
* - 验证消息过滤和验证逻辑
|
||||
* - 测试错误处理和异常情况
|
||||
* - 验证WebSocket消息广播功能
|
||||
*
|
||||
* 测试范围:
|
||||
* - 消息发送API测试
|
||||
* - 参数验证测试
|
||||
* - 错误处理测试
|
||||
* - 业务逻辑验证
|
||||
*
|
||||
* 最近修改:
|
||||
* - 2026-01-12: Bug修复 - 修复测试用例中的方法名和DTO结构 (修改者: moyin)
|
||||
* - 2026-01-12: 代码规范优化 - 创建测试文件,确保控制器功能的测试覆盖 (修改者: moyin)
|
||||
*
|
||||
* @author moyin
|
||||
* @version 1.0.1
|
||||
* @since 2026-01-12
|
||||
* @lastModified 2026-01-12
|
||||
*/
|
||||
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { HttpException, HttpStatus } from '@nestjs/common';
|
||||
import { ChatController } from './chat.controller';
|
||||
import { ZulipService } from './zulip.service';
|
||||
import { MessageFilterService } from './services/message_filter.service';
|
||||
import { CleanWebSocketGateway } from './clean_websocket.gateway';
|
||||
import { JwtAuthGuard } from '../auth/jwt_auth.guard';
|
||||
|
||||
// Mock JwtAuthGuard
|
||||
const mockJwtAuthGuard = {
|
||||
canActivate: jest.fn(() => true),
|
||||
};
|
||||
|
||||
describe('ChatController', () => {
|
||||
let controller: ChatController;
|
||||
let zulipService: jest.Mocked<ZulipService>;
|
||||
let messageFilterService: jest.Mocked<MessageFilterService>;
|
||||
let websocketGateway: jest.Mocked<CleanWebSocketGateway>;
|
||||
|
||||
beforeEach(async () => {
|
||||
const mockZulipService = {
|
||||
sendChatMessage: jest.fn(),
|
||||
};
|
||||
|
||||
const mockMessageFilterService = {
|
||||
validateMessage: jest.fn(),
|
||||
};
|
||||
|
||||
const mockWebSocketGateway = {
|
||||
broadcastToRoom: jest.fn(),
|
||||
getActiveConnections: jest.fn(),
|
||||
};
|
||||
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [ChatController],
|
||||
providers: [
|
||||
{
|
||||
provide: ZulipService,
|
||||
useValue: mockZulipService,
|
||||
},
|
||||
{
|
||||
provide: MessageFilterService,
|
||||
useValue: mockMessageFilterService,
|
||||
},
|
||||
{
|
||||
provide: CleanWebSocketGateway,
|
||||
useValue: mockWebSocketGateway,
|
||||
},
|
||||
{
|
||||
provide: JwtAuthGuard,
|
||||
useValue: mockJwtAuthGuard,
|
||||
},
|
||||
],
|
||||
})
|
||||
.overrideGuard(JwtAuthGuard)
|
||||
.useValue(mockJwtAuthGuard)
|
||||
.compile();
|
||||
|
||||
controller = module.get<ChatController>(ChatController);
|
||||
zulipService = module.get(ZulipService);
|
||||
messageFilterService = module.get(MessageFilterService);
|
||||
websocketGateway = module.get(CleanWebSocketGateway);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
|
||||
describe('sendMessage', () => {
|
||||
const validMessageDto = {
|
||||
content: 'Hello, world!',
|
||||
stream: 'general',
|
||||
topic: 'chat',
|
||||
userId: 'user123',
|
||||
scope: 'local',
|
||||
};
|
||||
|
||||
it('should reject REST API message sending and suggest WebSocket', async () => {
|
||||
// Act & Assert
|
||||
await expect(controller.sendMessage(validMessageDto)).rejects.toThrow(
|
||||
new HttpException(
|
||||
'聊天消息发送需要通过 WebSocket 连接。请使用 WebSocket 接口:wss://whaletownend.xinghangee.icu',
|
||||
HttpStatus.BAD_REQUEST,
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('should log the REST API request attempt', async () => {
|
||||
// Arrange
|
||||
const loggerSpy = jest.spyOn(controller['logger'], 'log');
|
||||
|
||||
// Act
|
||||
try {
|
||||
await controller.sendMessage(validMessageDto);
|
||||
} catch (error) {
|
||||
// Expected to throw
|
||||
}
|
||||
|
||||
// Assert
|
||||
expect(loggerSpy).toHaveBeenCalledWith('收到REST API聊天消息发送请求', {
|
||||
operation: 'sendMessage',
|
||||
content: validMessageDto.content.substring(0, 50),
|
||||
scope: validMessageDto.scope,
|
||||
timestamp: expect.any(String),
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle different message content lengths', async () => {
|
||||
// Arrange
|
||||
const longMessageDto = {
|
||||
...validMessageDto,
|
||||
content: 'a'.repeat(100), // Long message
|
||||
};
|
||||
|
||||
// Act & Assert
|
||||
await expect(controller.sendMessage(longMessageDto)).rejects.toThrow(HttpException);
|
||||
});
|
||||
|
||||
it('should handle empty message content', async () => {
|
||||
// Arrange
|
||||
const emptyMessageDto = { ...validMessageDto, content: '' };
|
||||
|
||||
// Act & Assert
|
||||
await expect(controller.sendMessage(emptyMessageDto)).rejects.toThrow(HttpException);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Error Handling', () => {
|
||||
it('should always throw HttpException for REST API requests', async () => {
|
||||
// Arrange
|
||||
const validMessageDto = {
|
||||
content: 'Hello, world!',
|
||||
stream: 'general',
|
||||
topic: 'chat',
|
||||
userId: 'user123',
|
||||
scope: 'local',
|
||||
};
|
||||
|
||||
// Act & Assert
|
||||
await expect(controller.sendMessage(validMessageDto)).rejects.toThrow(HttpException);
|
||||
});
|
||||
|
||||
it('should log error when REST API is used', async () => {
|
||||
// Arrange
|
||||
const validMessageDto = {
|
||||
content: 'Hello, world!',
|
||||
stream: 'general',
|
||||
topic: 'chat',
|
||||
userId: 'user123',
|
||||
scope: 'local',
|
||||
};
|
||||
|
||||
const loggerSpy = jest.spyOn(controller['logger'], 'error');
|
||||
|
||||
// Act
|
||||
try {
|
||||
await controller.sendMessage(validMessageDto);
|
||||
} catch (error) {
|
||||
// Expected to throw
|
||||
}
|
||||
|
||||
// Assert
|
||||
expect(loggerSpy).toHaveBeenCalledWith('REST API消息发送失败', {
|
||||
operation: 'sendMessage',
|
||||
error: expect.any(String),
|
||||
timestamp: expect.any(String),
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user