53c8644f创建于 2025年4月7日历史提交
import { Test, TestingModule } from '@nestjs/testing';
import { RoleService } from '../role.service';
import { getRepositoryToken } from '@nestjs/typeorm';
import { Role, Permission, Menu, User } from '@app/models';
import { I18nContext, I18nService } from 'nestjs-i18n';
import { Repository } from 'typeorm';
import { HttpException } from '@nestjs/common';

describe('Role Service', () => {
  let service: RoleService;
  let roleRepository: Repository<Role>;
  let permissionRepository: Repository<Permission>;
  let menuRepository: Repository<Menu>;
  let userRepository: Repository<User>;
  let i18nService: I18nService;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        RoleService,
        {
          provide: getRepositoryToken(Role),
          useClass: Repository,
        },
        {
          provide: getRepositoryToken(Permission),
          useClass: Repository,
        },
        {
          provide: getRepositoryToken(Menu),
          useClass: Repository,
        },
        {
          provide: getRepositoryToken(User),
          useClass: Repository,
        },
        {
          provide: I18nService,
          useValue: {
            t: jest.fn().mockReturnValue('mocked translation'),
          },
        },
      ],
    }).compile();

    jest.spyOn(I18nContext, 'current')
    .mockReturnValue({
      current: jest.fn().mockReturnValue({
        lang: ''
      })
    } as any)

    service = module.get<RoleService>(RoleService);
    roleRepository = module.get<Repository<Role>>(getRepositoryToken(Role));
    permissionRepository = module.get<Repository<Permission>>(getRepositoryToken(Permission));
    menuRepository = module.get<Repository<Menu>>(getRepositoryToken(Menu));
    userRepository = module.get<Repository<User>>(getRepositoryToken(User));
    i18nService = module.get<I18nService>(I18nService);
  });

  it('should be defined', () => {
    expect(service).toBeDefined();
  });

  describe('create', () => {
    it('should create a new role', async () => {
      const createRoleDto = { name: 'Admin', permissionIds: [1], menuIds: [1] };
      const mockRole = { id: 1, name: 'Admin', permission: [], menus: [] };

      jest.spyOn(roleRepository, 'findOne').mockResolvedValueOnce(null);
      jest.spyOn(permissionRepository, 'find').mockResolvedValueOnce([]);
      jest.spyOn(menuRepository, 'find').mockResolvedValueOnce([]);
      jest.spyOn(roleRepository, 'save').mockResolvedValueOnce(mockRole);

      const result = await service.create(createRoleDto, false);

      expect(result).toEqual(mockRole);
      expect(roleRepository.findOne).toHaveBeenCalledWith({ where: { name: 'Admin' } });
      expect(permissionRepository.find).toHaveBeenCalledWith({ where: { id: expect.anything() } });
      expect(menuRepository.find).toHaveBeenCalledWith({ where: { id: expect.anything() } });
      expect(roleRepository.save).toHaveBeenCalledWith({
        name: 'Admin',
        permission: [],
        menus: [],
      });
    });

    it('should throw an exception if role already exists', async () => {
      const createRoleDto = { name: 'Admin', permissionIds: [], menuIds: [] };
      const mockRole = { id: 1, name: 'Admin' };

      jest.spyOn(roleRepository, 'findOne').mockResolvedValueOnce(mockRole as any);

      await expect(service.create(createRoleDto, false)).rejects.toThrow(HttpException);
    });
  });

  describe('findAll', () => {
    it('should return all roles', async () => {
      const mockRoles = [{ id: 1, name: 'Admin' }];
      jest.spyOn(roleRepository, 'find').mockResolvedValueOnce(mockRoles as any);

      const result = await service.findAll();

      expect(result).toEqual(mockRoles);
      expect(roleRepository.find).toHaveBeenCalled();
    });
  });

  describe('findOne', () => {
    it('should return a role by id', async () => {
      const mockRole = { id: 1, name: 'Admin', menus: [], permission: [] };
      jest.spyOn(roleRepository, 'createQueryBuilder').mockReturnValueOnce({
        leftJoinAndSelect: jest.fn().mockReturnThis(),
        where: jest.fn().mockReturnThis(),
        getOne: jest.fn().mockResolvedValueOnce(mockRole),
      } as any);

      const result = await service.findOne('1');

      expect(result).toEqual(mockRole);
    });

    it('should throw an exception if role not found', async () => {
      jest.spyOn(roleRepository, 'createQueryBuilder').mockReturnValueOnce({
        leftJoinAndSelect: jest.fn().mockReturnThis(),
        where: jest.fn().mockReturnThis(),
        getOne: jest.fn().mockResolvedValueOnce(null),
      } as any);

      await expect(service.findOne('1')).rejects.toThrow(HttpException);
    });
  });

  describe('delete', () => {
    it('should delete a role', async () => {
      const mockRole = [{ id: 1, name: 'Admin' }];
      jest.spyOn(roleRepository, 'find').mockResolvedValueOnce(mockRole as any);
      jest.spyOn(userRepository, 'find').mockResolvedValueOnce([]);
      jest.spyOn(roleRepository, 'remove').mockResolvedValueOnce(mockRole as any);

      const result = await service.delete(1);

      expect(result).toEqual(mockRole);
      expect(roleRepository.find).toHaveBeenCalledWith({ where: { id: 1 } });
      expect(userRepository.find).toHaveBeenCalledWith({ where: { role: { id: 1 } }, take: 1 });
      expect(roleRepository.remove).toHaveBeenCalledWith(mockRole);
    });

    it('should throw an exception if role is associated with a user', async () => {
      const mockRole = [{ id: 1, name: 'Admin' }];
      const mockUser = [{ id: 1, name: 'User1', role: mockRole[0] }];
      jest.spyOn(roleRepository, 'find').mockResolvedValueOnce(mockRole as any);
      jest.spyOn(userRepository, 'find').mockResolvedValueOnce(mockUser as any);

      await expect(service.delete(1)).rejects.toThrow(HttpException);
    });
  });
});