【问题标题】:How to test custom Repository in Nestjs/TypeORM applications如何在 Nestjs/TypeORM 应用程序中测试自定义存储库
【发布时间】:2021-08-07 08:06:36
【问题描述】:

我正在尝试添加更多测试代码以提高示例代码的质量。

目前,我在测试UserRepository不是模拟UserRepository)时遇到问题,我在自定义UserRepository 中添加了一些自定义方法,如下所示。

@EntityRepository(UserEntity)
export class UserRepository extends Repository<UserEntity> {
  findByEmail(email: string): Promise<UserEntity> {
    return this.findOne({ email: email });
  }
}

所以我想验证 findOne 是从父 Repository 调用的。

我尝试添加以下测试代码。

describe('UserRepository', () => {
  let local;
  let parentMock;

  beforeEach(() => {
    local = Object.getPrototypeOf(UserRepository);
    parentMock = {
      new: jest.fn(),
      construtor: jest.fn(),
      findOne: jest.fn(),
    };
    Object.setPrototypeOf(UserRepository, parentMock);
  });

  afterEach(() => {
    Object.setPrototypeOf(UserRepository, local);
  });

  it('should call findOne', async () => {
    const findByEmailSpy = jest.spyOn(parentMock, 'findOne');
    const users = new UserRepository();
    await users.findByEmail('test@example.com');
    expect(parentMock.mock.calls.length).toBe(1);
    expect(findByEmailSpy).toBeCalledWith({
      email: 'test@example.com',
    });
  });
});

运行测试时,它抱怨new UserRepository() 没有constructor()。

有没有办法解决这个问题,或者有更好的方法来编写这些测试代码?

【问题讨论】:

    标签: nestjs typeorm


    【解决方案1】:

    为了正确测试用户存储库,必须模拟 findOne 方法。

    import { Test, TestingModule } from '@nestjs/testing';
    import { Repository } from 'typeorm';
    import { UserEntity } from './user.entity';
    import { UserRepository } from './user.repository';
    
    describe('UserRepository', () => {
      let userRepository: UserRepository;
    
      beforeEach(async () => {
        const module: TestingModule = await Test.createTestingModule({
          providers: [UserRepository],
        }).compile();
    
        userRepository = module.get<UserRepository>(UserRepository);
      });
    
      describe('findByEmail', () => {
        it('should return found user', async () => {
          const email = 'email';
          const user = {
            email,
          };
          const findOneSpy = jest
            .spyOn(userRepository, 'findOne')
            .mockResolvedValue(user as UserEntity);
    
          const foundUser = await userRepository.findByEmail(email);
          expect(foundUser).toEqual(user);
          expect(findOneSpy).toHaveBeenCalledWith(user);
        });
      });
    });
    
    

    【讨论】:

    • 如果在Repository中使用EntityManager和QueryBuilder,例如findByAuthor in the PostRepository,如何mock呢?
    • 对于 QueryBuilder,可以模拟如下:jest.spyOn(Repository.prototype, 'createQueryBuilder').mockReturnValue(SelectQueryBuilder.prototype); jest.spyOn(SelectQueryBuilder.prototype, 'where').mockReturnThis(); // the same goes for setParameter, skip and take methods jest.spyOn(SelectQueryBuilder.prototype, 'getMany').mockResolvedValue(data);
    • 不确定是否要模拟manager.findOne,使用this.manager.find 而不是this.find 的原因是什么?
    • 我添加了a test 让它工作。但是Repository 中的所有 readonly 属性都应该是可注入的,但它不像其他可注入组件那样按预期工作。
    • AbstractRepository 扩展时有什么想法吗?我创建了一个单独的question for it here
    猜你喜欢
    • 2021-06-07
    • 1970-01-01
    • 2022-07-07
    • 1970-01-01
    • 2020-07-02
    • 1970-01-01
    • 2021-01-07
    • 2022-08-05
    • 2021-06-08
    相关资源
    最近更新 更多