'unit test with mocking custom repository of typeorm

When I tried with basic repository provided typeorm, I think test is completed.

But to do 'unit test' with custom repository of typeorm is not working.

I think mocking custom repository has problem.

What I have to do for mocking custom repostitory?

Next are test file and source file to test.

Thanks.

quests.service.spec.ts

import { Test } from '@nestjs/testing';
import { getRepositoryToken } from '@nestjs/typeorm';
import { QuestsService } from 'src/quests/quests.service';
import { QuestRepository } from 'src/quests/repositories/quest.repository';
import { Repository } from 'typeorm';
import { Complete } from 'src/quests/entities/complete.entity';
import { Player } from 'src/players/entities/player.entity';

const mockRepository = () => ({
  create: jest.fn(),
  save: jest.fn(),
  findOne: jest.fn(),
});
const mockQuestsRepository = {
  save: jest.fn(),
  findOne: jest.fn(),
  findAllWithCompletes: jest.fn(),
  findOneWithCompletes: jest.fn(),
};

type MockRepository<T = any> = Partial<Record<keyof Repository<T>, jest.Mock>>;
type MockQuestRepository = Partial<Record<keyof QuestRepository, jest.Mock>>;

describe('QuestsService', () => {
  let service: QuestsService;
  let playersRepository: MockRepository<Player>;
  let completeRepository: MockRepository<Complete>;
  let questsRepository: MockQuestRepository;

  beforeAll(async () => {
    const module = await Test.createTestingModule({
      providers: [
        QuestsService,
        {
          provide: getRepositoryToken(Player),
          useValue: mockRepository(),
        },
        {
          provide: getRepositoryToken(Complete),
          useValue: mockRepository(),
        },
        {
          provide: QuestRepository,
          useValue: mockQuestsRepository,
        },
      ],
    }).compile();

    service = module.get<QuestsService>(QuestsService);
    playersRepository = module.get(getRepositoryToken(Player));
    completeRepository = module.get(getRepositoryToken(Complete));
    questsRepository = module.get(QuestRepository);
  });

  describe('questComplete', () => {
    it('should fail if quest does not exist', async () => {
      questsRepository.findOne.mockResolvedValue(undefined);
      const result = await service.questComplete(-1, 1);

      expect(result).toEqual({
        ok: false,
        message: 'cant find requested Quest.',
      });
    });

    it('should fail if player does not exist', async () => {
      questsRepository.findOne.mockResolvedValue(true);
      playersRepository.findOne.mockResolvedValue(undefined);
      const result = await service.questComplete(1, 1);

      expect(result).toEqual({
        ok: false,
        message: 'cant find player.',
      });
    });
  });
});

quests.service.ts

@Injectable()
export class QuestsService {
  constructor(
    @InjectRepository(Complete)
    private readonly completes: Repository<Complete>,
    private readonly quests: QuestRepository
  ) {}

  async questComplete(questId: number, playerId: number) {
    try {
      const quest = await this.quests.findOne({ id: questId });
      if (!quest)
        return { ok: false, message: 'cant find requested Quest.' };

      const player = await Player.findOne({ where: { id: playerId } });
      if (!player)
        return { ok: false, message: 'cant find player.' };

      const isCompleted = await this.completes.findOne({ quest, player });
      if (isCompleted)
        return { ok: false, message: 'quest is already completed.' };

      await this.completes.save(this.completes.create({ quest, player }));
      return { ok: true };
    } catch (error) {
      return { ok: false, message: 'quest cant be completed.' };
    }
  }
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source