Testing custom repositories (NestJS/TypeORM)

Custom repositories extend the base repository class and enrich it with several additional methods. This post covers unit and integration testing.

// user.repository.ts
@Injectable()
export class UserRepository extends Repository<UserEntity> {
  constructor(private dataSource: DataSource) {
    super(UserEntity, dataSource.createEntityManager());
  }

  async getById(id: string) {
    return this.findOne({ where: { id } });
  }
  // ...
}

Setup

Inject a custom repository into the service.

// user.service.ts
export class UserService {
  constructor(private readonly userRepository: UserRepository) {}

  async getById(id: string): Promise<User> {
    return this.userRepository.getById(id);
  }
  // ...
}

Pass entity class to the forFeature method.

// user.module.ts
@Module({
  imports: [
    TypeOrmModule.forFeature([UserEntity])],
    // ...
  ],
  providers: [UserService, UserRepository],
  // ...
})
export class UserModule {}

Unit testing

To properly unit-test the custom repository, mock some methods.

// user.repository.spec.ts
describe('UserRepository', () => {
  let userRepository: UserRepository;
  const dataSource = {
    createEntityManager: jest.fn()
  };

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        UserRepository,
        {
          provide: DataSource,
          useValue: dataSource
        }
      ]
    }).compile();

    userRepository = module.get<UserRepository>(UserRepository);
  });

  describe('getById', () => {
    it('should return found user', async () => {
      const id = 'id';
      const user = {
        id
      };
      const findOneSpy = jest
        .spyOn(userRepository, 'findOne')
        .mockResolvedValue(user as UserEntity);

      const foundUser = await userRepository.getById(id);
      expect(foundUser).toEqual(user);
      expect(findOneSpy).toHaveBeenCalledWith({ where: user });
    });
  });
});

Integration testing

Integration testing is more suitable when working with databases. Read more about it on Integration testing Node.js apps post

Boilerplate

Here is the link to the boilerplate I use for the development. It contains the examples mentioned above with more details.

Did you find this article valuable?

Support Željko Šević by becoming a sponsor. Any amount is appreciated!