Jest и TestingModule: unit-тесты провайдеров

↑ 6.4 Тестирование в NestJS · → Следующая

По желанию~3 мин чтенияУровень: junior

Зачем это на собесе

Как в Nest подменяют зависимости в тестах — аналог DI-подмены в .NET.

Объяснение

Test.createTestingModule собирает облегчённый модуль с нужными провайдерами и позволяет заменить зависимости.

describe("OrdersService", () => {
  let service: OrdersService;
  const repo = { findById: jest.fn(), save: jest.fn() };
 
  beforeEach(async () => {
    const moduleRef = await Test.createTestingModule({
      providers: [OrdersService, { provide: OrdersRepository, useValue: repo }],
    }).compile();
    service = moduleRef.get(OrdersService);
    jest.resetAllMocks();
  });
 
  it("бросает NotFound для неизвестного заказа", async () => {
    repo.findById.mockResolvedValue(null);
    await expect(service.find("42")).rejects.toBeInstanceOf(NotFoundException);
  });
 
  it("сохраняет заказ", async () => {
    repo.save.mockResolvedValue({ id: "1" });
    await service.create({ customer: "A", quantity: 1 });
    expect(repo.save).toHaveBeenCalledWith(expect.objectContaining({ customer: "A" }));
  });
});

Полезные приёмы:

  • overrideProvider(X).useValue(mock), useMocker для автоматических моков.
  • jest.useFakeTimers() для времени; jest.spyOn для частичных подмен.
  • Табличные тесты: it.each([...]).
  • Vitest — быстрая альтернатива Jest с совместимым API.

Нюансы и подводные камни

  • Тестируйте поведение, а не вызовы моков.
  • Не забывайте await перед expect(...).rejects.
  • Общие моки между тестами без сброса дают зависимые тесты.
  • Проверяйте типы: моки useValue не проверяются компилятором на соответствие интерфейсу.

Практика

  1. Напишите unit-тесты сервиса заказов с заменой репозитория.
  2. Используйте it.each для набора граничных случаев.
  3. Протестируйте код со временем через fake timers.

Вопросы с ответами

Связанные темы