concrete-crud.service.test.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. import { describe, it, expect, vi, beforeEach } from 'vitest';
  2. import { DataSource, ObjectLiteral } from 'typeorm';
  3. import { ConcreteCrudService } from '../../src/services/concrete-crud.service';
  4. import { AppDataSource, initializeDataSource } from '@d8d/shared-utils';
  5. // 测试实体类
  6. class TestEntity implements ObjectLiteral {
  7. id!: number;
  8. name!: string;
  9. }
  10. describe('ConcreteCrudService', () => {
  11. let mockDataSource: DataSource;
  12. let concreteService: ConcreteCrudService<TestEntity>;
  13. beforeEach(() => {
  14. mockDataSource = {
  15. getRepository: vi.fn().mockReturnValue({
  16. createQueryBuilder: vi.fn().mockReturnValue({
  17. leftJoinAndSelect: vi.fn().mockReturnThis(),
  18. andWhere: vi.fn().mockReturnThis(),
  19. orderBy: vi.fn().mockReturnThis(),
  20. skip: vi.fn().mockReturnThis(),
  21. take: vi.fn().mockReturnThis(),
  22. getManyAndCount: vi.fn().mockResolvedValue([[], 0])
  23. }),
  24. findOne: vi.fn().mockResolvedValue(null),
  25. create: vi.fn().mockImplementation((data) => ({ ...data, id: 1 })),
  26. save: vi.fn().mockImplementation((entity) => Promise.resolve(entity)),
  27. update: vi.fn().mockResolvedValue({ affected: 1 }),
  28. delete: vi.fn().mockResolvedValue({ affected: 1 })
  29. })
  30. } as any;
  31. // 在测试环境中初始化 AppDataSource
  32. initializeDataSource([TestEntity]);
  33. // 模拟 AppDataSource 的 getRepository 方法
  34. vi.spyOn(AppDataSource, 'getRepository').mockImplementation(mockDataSource.getRepository);
  35. concreteService = new ConcreteCrudService(TestEntity);
  36. });
  37. describe('构造函数', () => {
  38. it('应该正确初始化父类', () => {
  39. expect(concreteService).toBeDefined();
  40. expect(mockDataSource.getRepository).toHaveBeenCalledWith(TestEntity);
  41. });
  42. it('应该支持用户跟踪选项', () => {
  43. const serviceWithTracking = new ConcreteCrudService(
  44. TestEntity,
  45. { userTracking: { createdByField: 'creator' } }
  46. );
  47. expect(serviceWithTracking).toBeDefined();
  48. });
  49. it('应该支持关联字段选项', () => {
  50. const serviceWithRelations = new ConcreteCrudService(
  51. TestEntity,
  52. { relationFields: { relatedIds: { relationName: 'related', targetEntity: TestEntity } } }
  53. );
  54. expect(serviceWithRelations).toBeDefined();
  55. });
  56. });
  57. describe('继承的方法', () => {
  58. it('应该能够调用 getList 方法', async () => {
  59. const [data, total] = await concreteService.getList(1, 10);
  60. expect(data).toEqual([]);
  61. expect(total).toBe(0);
  62. });
  63. it('应该能够调用 getById 方法', async () => {
  64. const result = await concreteService.getById(1);
  65. expect(result).toBeNull();
  66. });
  67. it('应该能够调用 create 方法', async () => {
  68. const createData = { name: 'Test Entity' };
  69. const result = await concreteService.create(createData);
  70. expect(result).toBeDefined();
  71. expect(result.id).toBe(1);
  72. });
  73. it('应该能够调用 update 方法', async () => {
  74. const updateData = { name: 'Updated Entity' };
  75. const result = await concreteService.update(1, updateData);
  76. expect(result).toBeNull(); // 因为模拟的 findOne 返回 null
  77. });
  78. it('应该能够调用 delete 方法', async () => {
  79. const result = await concreteService.delete(1);
  80. expect(result).toBe(true);
  81. });
  82. });
  83. });