forked from datawhale/whale-town-end
test:添加管理后台的单元测试
This commit is contained in:
159
src/business/admin/admin.service.spec.ts
Normal file
159
src/business/admin/admin.service.spec.ts
Normal file
@@ -0,0 +1,159 @@
|
||||
import { NotFoundException } from '@nestjs/common';
|
||||
import { AdminService } from './admin.service';
|
||||
import { AdminCoreService } from '../../core/admin_core/admin_core.service';
|
||||
import { LogManagementService } from '../../core/utils/logger/log_management.service';
|
||||
import { Users } from '../../core/db/users/users.entity';
|
||||
|
||||
describe('AdminService', () => {
|
||||
let service: AdminService;
|
||||
|
||||
const adminCoreServiceMock: Pick<AdminCoreService, 'login' | 'resetUserPassword'> = {
|
||||
login: jest.fn(),
|
||||
resetUserPassword: jest.fn(),
|
||||
};
|
||||
|
||||
const usersServiceMock = {
|
||||
findAll: jest.fn(),
|
||||
findOne: jest.fn(),
|
||||
};
|
||||
|
||||
const logManagementServiceMock: Pick<LogManagementService, 'getRuntimeLogTail' | 'getLogDirAbsolutePath'> = {
|
||||
getRuntimeLogTail: jest.fn(),
|
||||
getLogDirAbsolutePath: jest.fn(),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
service = new AdminService(
|
||||
adminCoreServiceMock as unknown as AdminCoreService,
|
||||
usersServiceMock as any,
|
||||
logManagementServiceMock as unknown as LogManagementService,
|
||||
);
|
||||
});
|
||||
|
||||
it('should login admin successfully', async () => {
|
||||
(adminCoreServiceMock.login as jest.Mock).mockResolvedValue({
|
||||
admin: { id: '1', username: 'admin', nickname: '管理员', role: 9 },
|
||||
access_token: 'token',
|
||||
expires_at: 123,
|
||||
});
|
||||
|
||||
const res = await service.login('admin', 'Admin123456');
|
||||
|
||||
expect(adminCoreServiceMock.login).toHaveBeenCalledWith({ identifier: 'admin', password: 'Admin123456' });
|
||||
expect(res.success).toBe(true);
|
||||
expect(res.data?.admin?.role).toBe(9);
|
||||
expect(res.message).toBe('管理员登录成功');
|
||||
});
|
||||
|
||||
it('should handle login failure', async () => {
|
||||
(adminCoreServiceMock.login as jest.Mock).mockRejectedValue(new Error('密码错误'));
|
||||
|
||||
const res = await service.login('admin', 'bad');
|
||||
|
||||
expect(res.success).toBe(false);
|
||||
expect(res.error_code).toBe('ADMIN_LOGIN_FAILED');
|
||||
expect(res.message).toBe('密码错误');
|
||||
});
|
||||
|
||||
it('should handle non-Error login failure', async () => {
|
||||
(adminCoreServiceMock.login as jest.Mock).mockRejectedValue('boom');
|
||||
|
||||
const res = await service.login('admin', 'bad');
|
||||
|
||||
expect(res.success).toBe(false);
|
||||
expect(res.error_code).toBe('ADMIN_LOGIN_FAILED');
|
||||
expect(res.message).toBe('管理员登录失败');
|
||||
});
|
||||
|
||||
it('should list users with pagination', async () => {
|
||||
const user = {
|
||||
id: BigInt(1),
|
||||
username: 'u1',
|
||||
nickname: 'U1',
|
||||
email: 'u1@test.com',
|
||||
email_verified: true,
|
||||
phone: null,
|
||||
avatar_url: null,
|
||||
role: 1,
|
||||
created_at: new Date('2025-01-01T00:00:00Z'),
|
||||
updated_at: new Date('2025-01-02T00:00:00Z'),
|
||||
} as unknown as Users;
|
||||
|
||||
usersServiceMock.findAll.mockResolvedValue([user]);
|
||||
|
||||
const res = await service.listUsers(100, 0);
|
||||
|
||||
expect(usersServiceMock.findAll).toHaveBeenCalledWith(100, 0);
|
||||
expect(res.success).toBe(true);
|
||||
expect(res.data?.users).toHaveLength(1);
|
||||
expect(res.data?.users[0]).toMatchObject({
|
||||
id: '1',
|
||||
username: 'u1',
|
||||
nickname: 'U1',
|
||||
role: 1,
|
||||
});
|
||||
});
|
||||
|
||||
it('should get user by id', async () => {
|
||||
const user = {
|
||||
id: BigInt(3),
|
||||
username: 'u3',
|
||||
nickname: 'U3',
|
||||
email: null,
|
||||
email_verified: false,
|
||||
phone: '123',
|
||||
avatar_url: null,
|
||||
role: 1,
|
||||
created_at: new Date('2025-01-01T00:00:00Z'),
|
||||
updated_at: new Date('2025-01-02T00:00:00Z'),
|
||||
} as unknown as Users;
|
||||
|
||||
usersServiceMock.findOne.mockResolvedValue(user);
|
||||
|
||||
const res = await service.getUser(BigInt(3));
|
||||
|
||||
expect(usersServiceMock.findOne).toHaveBeenCalledWith(BigInt(3));
|
||||
expect(res.success).toBe(true);
|
||||
expect(res.data?.user).toMatchObject({ id: '3', username: 'u3', nickname: 'U3' });
|
||||
});
|
||||
|
||||
it('should reset user password', async () => {
|
||||
usersServiceMock.findOne.mockResolvedValue({ id: BigInt(2) } as unknown as Users);
|
||||
(adminCoreServiceMock.resetUserPassword as jest.Mock).mockResolvedValue(undefined);
|
||||
|
||||
const res = await service.resetPassword(BigInt(2), 'NewPass1234');
|
||||
|
||||
expect(usersServiceMock.findOne).toHaveBeenCalledWith(BigInt(2));
|
||||
expect(adminCoreServiceMock.resetUserPassword).toHaveBeenCalledWith(BigInt(2), 'NewPass1234');
|
||||
expect(res).toEqual({ success: true, message: '密码重置成功' });
|
||||
});
|
||||
|
||||
it('should throw NotFoundException when resetting password for missing user', async () => {
|
||||
usersServiceMock.findOne.mockRejectedValue(new Error('not found'));
|
||||
|
||||
await expect(service.resetPassword(BigInt(999), 'NewPass1234')).rejects.toBeInstanceOf(NotFoundException);
|
||||
});
|
||||
|
||||
it('should get runtime logs', async () => {
|
||||
(logManagementServiceMock.getRuntimeLogTail as jest.Mock).mockResolvedValue({
|
||||
file: 'dev.log',
|
||||
updated_at: '2025-01-01T00:00:00.000Z',
|
||||
lines: ['a', 'b'],
|
||||
});
|
||||
|
||||
const res = await service.getRuntimeLogs(2);
|
||||
|
||||
expect(logManagementServiceMock.getRuntimeLogTail).toHaveBeenCalledWith({ lines: 2 });
|
||||
expect(res.success).toBe(true);
|
||||
expect(res.data?.file).toBe('dev.log');
|
||||
expect(res.data?.lines).toEqual(['a', 'b']);
|
||||
});
|
||||
|
||||
it('should expose log dir absolute path', () => {
|
||||
(logManagementServiceMock.getLogDirAbsolutePath as jest.Mock).mockReturnValue('/abs/logs');
|
||||
|
||||
expect(service.getLogDirAbsolutePath()).toBe('/abs/logs');
|
||||
expect(logManagementServiceMock.getLogDirAbsolutePath).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user