refactor(auth): 重构认证模块架构 - 将Gateway层组件从Business层分离
范围: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层专注于业务逻辑和服务 - 符合分层架构设计原则
This commit is contained in:
209
src/gateway/auth/login.controller.spec.ts
Normal file
209
src/gateway/auth/login.controller.spec.ts
Normal file
@@ -0,0 +1,209 @@
|
||||
/**
|
||||
* LoginController 单元测试
|
||||
*
|
||||
* 功能描述:
|
||||
* - 测试登录控制器的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 { LoginController } from './login.controller';
|
||||
import { LoginService } from '../../business/auth/login.service';
|
||||
|
||||
describe('LoginController', () => {
|
||||
let controller: LoginController;
|
||||
let loginService: jest.Mocked<LoginService>;
|
||||
let mockResponse: jest.Mocked<Response>;
|
||||
|
||||
beforeEach(async () => {
|
||||
const mockLoginService = {
|
||||
login: jest.fn(),
|
||||
githubOAuth: jest.fn(),
|
||||
sendPasswordResetCode: jest.fn(),
|
||||
resetPassword: jest.fn(),
|
||||
changePassword: jest.fn(),
|
||||
verificationCodeLogin: jest.fn(),
|
||||
sendLoginVerificationCode: jest.fn(),
|
||||
refreshAccessToken: jest.fn(),
|
||||
debugVerificationCode: jest.fn(),
|
||||
};
|
||||
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [LoginController],
|
||||
providers: [
|
||||
{
|
||||
provide: LoginService,
|
||||
useValue: mockLoginService,
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
controller = module.get<LoginController>(LoginController);
|
||||
loginService = module.get(LoginService);
|
||||
|
||||
// Mock Response object
|
||||
mockResponse = {
|
||||
status: jest.fn().mockReturnThis(),
|
||||
json: jest.fn().mockReturnThis(),
|
||||
} as any;
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
|
||||
describe('login', () => {
|
||||
it('should handle successful login', async () => {
|
||||
const loginDto = {
|
||||
identifier: 'testuser',
|
||||
password: 'password123'
|
||||
};
|
||||
|
||||
const mockResult = {
|
||||
success: true,
|
||||
data: {
|
||||
user: {
|
||||
id: '1',
|
||||
username: 'testuser',
|
||||
nickname: '测试用户',
|
||||
role: 1,
|
||||
created_at: new Date()
|
||||
},
|
||||
access_token: 'token',
|
||||
refresh_token: 'refresh_token',
|
||||
expires_in: 3600,
|
||||
token_type: 'Bearer',
|
||||
message: '登录成功'
|
||||
},
|
||||
message: '登录成功'
|
||||
};
|
||||
|
||||
loginService.login.mockResolvedValue(mockResult);
|
||||
|
||||
await controller.login(loginDto, mockResponse);
|
||||
|
||||
expect(loginService.login).toHaveBeenCalledWith({
|
||||
identifier: 'testuser',
|
||||
password: 'password123'
|
||||
});
|
||||
expect(mockResponse.status).toHaveBeenCalledWith(HttpStatus.OK);
|
||||
expect(mockResponse.json).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
|
||||
it('should handle login failure', async () => {
|
||||
const loginDto = {
|
||||
identifier: 'testuser',
|
||||
password: 'wrongpassword'
|
||||
};
|
||||
|
||||
const mockResult = {
|
||||
success: false,
|
||||
message: '用户名或密码错误',
|
||||
error_code: 'LOGIN_FAILED'
|
||||
};
|
||||
|
||||
loginService.login.mockResolvedValue(mockResult);
|
||||
|
||||
await controller.login(loginDto, mockResponse);
|
||||
|
||||
expect(mockResponse.status).toHaveBeenCalledWith(HttpStatus.UNAUTHORIZED);
|
||||
expect(mockResponse.json).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('githubOAuth', () => {
|
||||
it('should handle GitHub OAuth successfully', async () => {
|
||||
const githubDto = {
|
||||
github_id: '12345',
|
||||
username: 'githubuser',
|
||||
nickname: 'GitHub User',
|
||||
email: 'github@example.com'
|
||||
};
|
||||
|
||||
const mockResult = {
|
||||
success: true,
|
||||
data: {
|
||||
user: {
|
||||
id: '1',
|
||||
username: 'githubuser',
|
||||
nickname: 'GitHub User',
|
||||
role: 1,
|
||||
created_at: new Date()
|
||||
},
|
||||
access_token: 'token',
|
||||
refresh_token: 'refresh_token',
|
||||
expires_in: 3600,
|
||||
token_type: 'Bearer',
|
||||
message: 'GitHub登录成功'
|
||||
},
|
||||
message: 'GitHub登录成功'
|
||||
};
|
||||
|
||||
loginService.githubOAuth.mockResolvedValue(mockResult);
|
||||
|
||||
await controller.githubOAuth(githubDto, mockResponse);
|
||||
|
||||
expect(loginService.githubOAuth).toHaveBeenCalledWith(githubDto);
|
||||
expect(mockResponse.status).toHaveBeenCalledWith(HttpStatus.OK);
|
||||
expect(mockResponse.json).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('refreshToken', () => {
|
||||
it('should handle token refresh successfully', async () => {
|
||||
const refreshTokenDto = {
|
||||
refresh_token: 'valid_refresh_token'
|
||||
};
|
||||
|
||||
const mockResult = {
|
||||
success: true,
|
||||
data: {
|
||||
access_token: 'new_access_token',
|
||||
refresh_token: 'new_refresh_token',
|
||||
expires_in: 3600,
|
||||
token_type: 'Bearer'
|
||||
},
|
||||
message: '令牌刷新成功'
|
||||
};
|
||||
|
||||
loginService.refreshAccessToken.mockResolvedValue(mockResult);
|
||||
|
||||
await controller.refreshToken(refreshTokenDto, mockResponse);
|
||||
|
||||
expect(loginService.refreshAccessToken).toHaveBeenCalledWith('valid_refresh_token');
|
||||
expect(mockResponse.status).toHaveBeenCalledWith(HttpStatus.OK);
|
||||
expect(mockResponse.json).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
|
||||
it('should handle token refresh failure', async () => {
|
||||
const refreshTokenDto = {
|
||||
refresh_token: 'invalid_refresh_token'
|
||||
};
|
||||
|
||||
const mockResult = {
|
||||
success: false,
|
||||
message: '刷新令牌无效或已过期',
|
||||
error_code: 'TOKEN_REFRESH_FAILED'
|
||||
};
|
||||
|
||||
loginService.refreshAccessToken.mockResolvedValue(mockResult);
|
||||
|
||||
await controller.refreshToken(refreshTokenDto, mockResponse);
|
||||
|
||||
expect(mockResponse.status).toHaveBeenCalledWith(HttpStatus.UNAUTHORIZED);
|
||||
expect(mockResponse.json).toHaveBeenCalledWith(mockResult);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user