范围:src/gateway/auth/, src/business/auth/, src/app.module.ts 涉及文件: - 新增:src/gateway/auth/ 目录及所有文件 - 移动:Controller、Guard、Decorator、DTO从business层移至gateway层 - 修改:src/business/auth/index.ts(移除Gateway层组件导出) - 修改:src/app.module.ts(使用AuthGatewayModule替代AuthModule) 主要改进: - 明确Gateway层和Business层的职责边界 - Controller、Guard、Decorator属于Gateway层职责 - Business层专注于业务逻辑和服务 - 符合分层架构设计原则
232 lines
7.0 KiB
TypeScript
232 lines
7.0 KiB
TypeScript
/**
|
|
* RegisterController 单元测试
|
|
*
|
|
* 功能描述:
|
|
* - 测试注册控制器的HTTP请求处理
|
|
* - 验证API响应格式和状态码
|
|
* - 测试邮箱验证流程
|
|
*
|
|
* 最近修改:
|
|
* - 2026-01-14: 架构重构 - 从business层移动到gateway层 (修改者: moyin)
|
|
* - 2026-01-12: 代码规范优化 - 创建缺失的控制器测试文件 (修改者: moyin)
|
|
*
|
|
* @author moyin
|
|
* @version 1.1.0
|
|
* @since 2026-01-12
|
|
* @lastModified 2026-01-14
|
|
*/
|
|
|
|
import { Test, TestingModule } from '@nestjs/testing';
|
|
import { Response } from 'express';
|
|
import { HttpStatus } from '@nestjs/common';
|
|
import { RegisterController } from './register.controller';
|
|
import { RegisterService } from '../../business/auth/register.service';
|
|
|
|
describe('RegisterController', () => {
|
|
let controller: RegisterController;
|
|
let registerService: jest.Mocked<RegisterService>;
|
|
let mockResponse: jest.Mocked<Response>;
|
|
|
|
beforeEach(async () => {
|
|
const mockRegisterService = {
|
|
register: jest.fn(),
|
|
sendEmailVerification: jest.fn(),
|
|
verifyEmailCode: jest.fn(),
|
|
resendEmailVerification: jest.fn(),
|
|
};
|
|
|
|
const module: TestingModule = await Test.createTestingModule({
|
|
controllers: [RegisterController],
|
|
providers: [
|
|
{
|
|
provide: RegisterService,
|
|
useValue: mockRegisterService,
|
|
},
|
|
],
|
|
}).compile();
|
|
|
|
controller = module.get<RegisterController>(RegisterController);
|
|
registerService = module.get(RegisterService);
|
|
|
|
// Mock Response object
|
|
mockResponse = {
|
|
status: jest.fn().mockReturnThis(),
|
|
json: jest.fn().mockReturnThis(),
|
|
} as any;
|
|
});
|
|
|
|
it('should be defined', () => {
|
|
expect(controller).toBeDefined();
|
|
});
|
|
|
|
describe('register', () => {
|
|
it('should handle successful registration', async () => {
|
|
const registerDto = {
|
|
username: 'newuser',
|
|
password: 'password123',
|
|
nickname: '新用户',
|
|
email: 'newuser@example.com',
|
|
email_verification_code: '123456'
|
|
};
|
|
|
|
const mockResult = {
|
|
success: true,
|
|
data: {
|
|
user: {
|
|
id: '1',
|
|
username: 'newuser',
|
|
nickname: '新用户',
|
|
role: 1,
|
|
created_at: new Date()
|
|
},
|
|
access_token: 'token',
|
|
refresh_token: 'refresh_token',
|
|
expires_in: 3600,
|
|
token_type: 'Bearer',
|
|
is_new_user: true,
|
|
message: '注册成功'
|
|
},
|
|
message: '注册成功'
|
|
};
|
|
|
|
registerService.register.mockResolvedValue(mockResult);
|
|
|
|
await controller.register(registerDto, mockResponse);
|
|
|
|
expect(registerService.register).toHaveBeenCalledWith(registerDto);
|
|
expect(mockResponse.status).toHaveBeenCalledWith(HttpStatus.CREATED);
|
|
expect(mockResponse.json).toHaveBeenCalledWith(mockResult);
|
|
});
|
|
|
|
it('should handle registration failure', async () => {
|
|
const registerDto = {
|
|
username: 'existinguser',
|
|
password: 'password123',
|
|
nickname: '用户'
|
|
};
|
|
|
|
const mockResult = {
|
|
success: false,
|
|
message: '用户名已存在',
|
|
error_code: 'REGISTER_FAILED'
|
|
};
|
|
|
|
registerService.register.mockResolvedValue(mockResult);
|
|
|
|
await controller.register(registerDto, mockResponse);
|
|
|
|
expect(mockResponse.status).toHaveBeenCalledWith(HttpStatus.BAD_REQUEST);
|
|
expect(mockResponse.json).toHaveBeenCalledWith(mockResult);
|
|
});
|
|
});
|
|
|
|
describe('sendEmailVerification', () => {
|
|
it('should handle email verification in production mode', async () => {
|
|
const sendEmailDto = {
|
|
email: 'test@example.com'
|
|
};
|
|
|
|
const mockResult = {
|
|
success: true,
|
|
data: { is_test_mode: false },
|
|
message: '验证码已发送,请查收邮件'
|
|
};
|
|
|
|
registerService.sendEmailVerification.mockResolvedValue(mockResult);
|
|
|
|
await controller.sendEmailVerification(sendEmailDto, mockResponse);
|
|
|
|
expect(registerService.sendEmailVerification).toHaveBeenCalledWith('test@example.com');
|
|
expect(mockResponse.status).toHaveBeenCalledWith(HttpStatus.OK);
|
|
expect(mockResponse.json).toHaveBeenCalledWith(mockResult);
|
|
});
|
|
|
|
it('should handle email verification in test mode', async () => {
|
|
const sendEmailDto = {
|
|
email: 'test@example.com'
|
|
};
|
|
|
|
const mockResult = {
|
|
success: false,
|
|
data: {
|
|
verification_code: '123456',
|
|
is_test_mode: true
|
|
},
|
|
message: '⚠️ 测试模式:验证码已生成但未真实发送。请在控制台查看验证码,或配置邮件服务以启用真实发送。',
|
|
error_code: 'TEST_MODE_ONLY'
|
|
};
|
|
|
|
registerService.sendEmailVerification.mockResolvedValue(mockResult);
|
|
|
|
await controller.sendEmailVerification(sendEmailDto, mockResponse);
|
|
|
|
expect(mockResponse.status).toHaveBeenCalledWith(HttpStatus.PARTIAL_CONTENT);
|
|
expect(mockResponse.json).toHaveBeenCalledWith(mockResult);
|
|
});
|
|
});
|
|
|
|
describe('verifyEmail', () => {
|
|
it('should handle email verification successfully', async () => {
|
|
const verifyEmailDto = {
|
|
email: 'test@example.com',
|
|
verification_code: '123456'
|
|
};
|
|
|
|
const mockResult = {
|
|
success: true,
|
|
message: '邮箱验证成功'
|
|
};
|
|
|
|
registerService.verifyEmailCode.mockResolvedValue(mockResult);
|
|
|
|
await controller.verifyEmail(verifyEmailDto, mockResponse);
|
|
|
|
expect(registerService.verifyEmailCode).toHaveBeenCalledWith('test@example.com', '123456');
|
|
expect(mockResponse.status).toHaveBeenCalledWith(HttpStatus.OK);
|
|
expect(mockResponse.json).toHaveBeenCalledWith(mockResult);
|
|
});
|
|
|
|
it('should handle invalid verification code', async () => {
|
|
const verifyEmailDto = {
|
|
email: 'test@example.com',
|
|
verification_code: '000000'
|
|
};
|
|
|
|
const mockResult = {
|
|
success: false,
|
|
message: '验证码错误',
|
|
error_code: 'INVALID_VERIFICATION_CODE'
|
|
};
|
|
|
|
registerService.verifyEmailCode.mockResolvedValue(mockResult);
|
|
|
|
await controller.verifyEmail(verifyEmailDto, mockResponse);
|
|
|
|
expect(mockResponse.status).toHaveBeenCalledWith(HttpStatus.BAD_REQUEST);
|
|
expect(mockResponse.json).toHaveBeenCalledWith(mockResult);
|
|
});
|
|
});
|
|
|
|
describe('resendEmailVerification', () => {
|
|
it('should handle resend email verification successfully', async () => {
|
|
const sendEmailDto = {
|
|
email: 'test@example.com'
|
|
};
|
|
|
|
const mockResult = {
|
|
success: true,
|
|
data: { is_test_mode: false },
|
|
message: '验证码已重新发送,请查收邮件'
|
|
};
|
|
|
|
registerService.resendEmailVerification.mockResolvedValue(mockResult);
|
|
|
|
await controller.resendEmailVerification(sendEmailDto, mockResponse);
|
|
|
|
expect(registerService.resendEmailVerification).toHaveBeenCalledWith('test@example.com');
|
|
expect(mockResponse.status).toHaveBeenCalledWith(HttpStatus.OK);
|
|
expect(mockResponse.json).toHaveBeenCalledWith(mockResult);
|
|
});
|
|
});
|
|
});
|