Search code examples
nestjstypeorm

How to test custom Repository in Nestjs/TypeORM applications


I am trying to add more testing codes to improve the quality of my sample codes.

Currently, I have a problem when testing UserRepository (not mock UserRepository), there are some custom methods I added in my custom UserRepository like this.

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

So I want to verify the findOne is called from the parent Repository.

I tried to add the following testing codes.

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('[email protected]');
    expect(parentMock.mock.calls.length).toBe(1);
    expect(findByEmailSpy).toBeCalledWith({
      email: '[email protected]',
    });
  });
});

When running the tests, it complains there is no constructor() for new UserRepository().

Is there any way to fix this issue, or a better way to write these testing codes?


Solution

  • In order to properly test the user repository, findOne method has to be mocked.

    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);
        });
      });
    });