Testing custom repositories (NestJS/TypeORM)
Custom repositories extend the base repository class and enrich it with several additional methods. This post covers the 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.tsexport 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.tsdescribe('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.