1

I am testing Employee service in Nestjs with Typeorm. The service has a injected employees repository. My test strategy is to mock a simple repostiory for testing the service.

import { Test, TestingModule } from '@nestjs/testing';
import { getRepositoryToken } from '@nestjs/typeorm';
import { getRepository, Repository } from 'typeorm';
import { CreateEmployeeDto } from './dto/create-employee.dto';
import { Employee } from './employee.entity';
import { EmployeesService } from './employees.service';
describe('EmployeesService', () => {
  let service: EmployeesService;

  const mockEmployeesRepository = {
    save: jest.fn().mockImplementation((dto: CreateEmployeeDto) => {
      return Promise.resolve({
        EmployeeID: Math.ceil(Math.random() * 10),
        ...dto,
      });
    }),
  };

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        EmployeesService,
        {
          provide: getRepositoryToken(Employee),
          useValue: mockEmployeesRepository,
        },
      ],
    }).compile();

    service = module.get<EmployeesService>(EmployeesService);
  });

  it('should be defined', () => {
    expect(service).toBeDefined();
  });
}

But I got EmployeesService › should be defined error. I just cannot figure out why EmployeesService not working in this simple test, even after check Inject TypeORM repository into NestJS service for mock data testing

more error message:

EmployeesService › should be defined

    expect(received).toBeDefined()

    Received: undefined

      35 |
      36 |   it('should be defined', () => {  
    > 37 |     expect(service).toBeDefined(); 
         |                     ^

employees.service.ts

@Injectable()
export class EmployeesService {
  constructor(
    @InjectRepository(Employee, 'db1')
    private employeesRepository: Repository<Employee>,
  ) {}

  findById(id: number): Promise<Employee> {
    return this.employeesRepository.findOneOrFail(id);
  }

  async createEmployee(createEmployeeDto: CreateEmployeeDto) {
    const newEmployee = createEmployeeDto;
    try {
      await this.employeesRepository.save(newEmployee);
    } catch (error) {
      throw new BadRequestException('Cannot create employee');
    }

    return newEmployee;
  }

  async deleteEmployee(id: number) {
    try {
      return await this.employeesRepository.delete(id);
    } catch (error) {
      throw new BadRequestException('Cannot delete employee');
    }
  }

  async updateEmployee(id: number, body: UpdateEmployeeDto) {
    const employee = this.employeesRepository.findOne(id);
    if (!employee) {
      throw new NotFoundException('Employee not found');
    }

    const updatedEmployee = await this.employeesRepository.update(id, body);

    return this.employeesRepository.findOne(id);
  }
}
Tim Woohoo
  • 470
  • 1
  • 7
  • 17

1 Answers1

1

This is your EmployeeService constructor:

constructor(
    @InjectRepository(Employee, 'db1')
    private employeesRepository: Repository<Employee>,
  ) {}

You are injecting two things but you are not passing both. You pass only one:

const module: TestingModule = await Test.createTestingModule({
      providers: [
        EmployeesService,
        {
          provide: getRepositoryToken(Employee),
          useValue: mockEmployeesRepository,
        },
      ],
    }).compile();

This module is an isolated DI container. You have to list what injected into the service

Yilmaz
  • 35,338
  • 10
  • 157
  • 202