Jest.js 如何在TypeORM中模仿EntityManger?

rdlzhqv9  于 2023-09-28  发布在  Jest
关注(0)|答案(2)|浏览(172)

我有下面的代码来模拟我的NestJS服务的entityManager,它在某种程度上工作,但问题是指定findOne应该为不同的实体返回什么。

{
      provide: getEntityManagerToken(),
      useFactory: (connection: Connection) => {
        const entityManager = {
          getRepository: jest.fn(() => {
            return {
              findOne: jest.fn().mockResolvedValue({}),
              save: jest.fn().mockResolvedValue(carData),
              createQueryBuilder: jest.fn(() => ({
                select: jest.fn().mockReturnThis(),
                from: jest.fn().mockReturnThis(),
                leftJoinAndSelect: jest.fn().mockReturnThis(),
                where: jest.fn().mockReturnThis(),
                addGroupBy: jest.fn().mockReturnThis(),
                groupBy: jest.fn().mockReturnThis(),
                getOne: jest.fn().mockResolvedValue(''),
              })),
            };
          }),
        };
        return entityManager;
      },
    },

我的服务看起来像下面的代码:

export class CarService {
  constructor(
    @InjectEntityManager()
    private readonly entityManager: EntityManager,
  ) {
    this.carRepository = entityManager.getRepository(Car);
    this.modelRepository = entityManager.getRepository(Model);
   }
    
      const car = await this.carRepository.findOne(data.id);

      const model = await this.modelRepository.findOne(data.modelId);

如何模拟this.carRepository中的findOne结果与this.modelRepository中的findOne结果不同,因为它们都将在同一服务中调用。

i7uq4tfw

i7uq4tfw1#

我们可以使用EntityManager API来创建具有多个存储库的事务,如果这些操作中的任何一个失败,这些存储库可以自动执行回滚,并且在测试中,我们可以使用Singleton模式来定义此实体的模拟,该实体允许我们返回这些存储库的相同示例,以测试所有这些读写操作是否已按预期执行。例如

import { createMock } from '@golevelup/ts-jest';
import { Test, TestingModule } from '@nestjs/testing';
import { EntityManager } from 'typeorm';

describe('MyService', () => {
  let service: MyService;
  let entityManager: EntityManager;
  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        MyService,
        { provide: EntityManager, useValue: createMock<EntityManager>() },
      ],
    }).compile();

    service = module.get(CatalogsService);
    entityManager = module.get(EntityManager);
  });
  
  it('should call a transaction correctly', async () => {
    const mockEntityManager = {
      save: jest.fn(),
      getCustomRepository: jest.fn((fn) => mockEntityManager[fn] || (mockEntityManager[fn] = createMock<typeof fn>())),
    };
    const spyTransaction = (entityManager.transaction as jest.Mock).mockImplementation((cb) => cb(mockEntityManager));
    const firstRepo: FirstRepository = mockEntityManager.getCustomRepository(SubCatalogRepository);
    const secondRepo: SecondRepository = mockEntityManager.getCustomRepository(SecondRepository);
    await service.saveSomething('MOCK DATA');

    expect(spyTransaction).toHaveBeenCalled();
    expect(firstRepo.save).toHaveBeenCalled();
    expect(secondRepo.save).toHaveBeenCalled();
    expect(mockEntityManager.save).toHaveBeenCalled();
  });
});

正如我们所看到的,模仿这些外部服务非常容易,比如TypeORM EntityManager等。使用createMock函数,该函数自动注入Jest模拟函数来替换我们的代码所依赖的外部实现,这在单元测试中应该不重要。
编码愉快!小于3个

kcwpcxri

kcwpcxri2#

下面的代码对我很有用,我觉得很容易阅读,不需要外部库,只需要使用Jest。

describe('MyService', () => {
  let service: MyService;
  let entityManager: EntityManager;
  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        MyService,
        { provide: EntityManager, useValue: {
          query: jest.fn(),
          // you can mock other functions inside
          // the entity manager object, my case only needed query method
          }
        },
      ],
    }).compile();

    service = module.get(MyService);
    entityManager = module.get(EntityManager);
  });

//... rest of your testing

})

相关问题