#Mocking nested services

33 messages · Page 1 of 1 (latest)

pliant rain
#

I have EmployeeService with the constructer

constructor(private readonly apiRepository: ApiRepository){
        console.log("ApiRepository:",
            apiRepository
        )
        this._employees = [];
    }

in the unit test I have the following:

beforeEach(async () => {

            const mockApiRepository = {
                getEmployees: jest.fn().mockResolvedValue(employeeEntities),
            };

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


            employeesService = module.get<EmployeesService>(EmployeesService);
            apiRepository = module.get<ApiRepository>(ApiRepository);
        });```
getEmployees is the function that im calling in the service.


```ts
it('should be defined',
            () => {
                expect(apiRepository).toBeDefined();
                expect(employeesService).toBeDefined();
            }
        );```
succeeds even tho the console.log in the constructer prints undefined.
tldr: apiRepository is not correctly injected and is undefined in EmployeeService.
open mesaBOT
#

This message has been acknowledged by @pliant rain, <t:1730111187:R>

pliant rain
#

I also tried automatically mocking ApiRepository as described in https://docs.nestjs.com/fundamentals/testing#auto-mocking

#

i still get:
Cannot read properties of undefined (reading 'getEmployees')

wet flax
#

What does your EmployeesService look like? How does it inject ApiRepository?

pliant rain
#
export class EmployeesService {

    constructor(private readonly apiRepository: ApiRepository){
        this._employees = [];
    }
...}
#

@wet flax this is how ApiRepository is injected

#

keep in mind that when i run the app.module, which has both as providers, everything works correctly

wet flax
#

And this class has the @Injectable() decorator?

#

Are the imports the same in the service and the spec?

pliant rain
wet flax
#

Hmm, can you share a link to your code then? something isn't lining up here and the code blocks aren't quite representing it

pliant rain
#

i sadly cant share the whole code

#

i will try to share them here as much as possible

wet flax
#

Can you make a reproduction that shows the same issue?

pliant rain
#

will try

pliant rain
#
import { Injectable } from '@nestjs/common';
import { EmployeeEntity } from './entities/employees.entity';
import { ApiRepository } from "../api/api.repository";

@Injectable()
export class EmployeesService {

    constructor(private readonly apiRepository: ApiRepository){
        this._employees = [];
    }

    private _employees: EmployeeEntity[];

    ...

/**
     * Retrieves all employees from api and updates the employees list.
     * Returns true if an update was needed.
     * @returns Returns a promise that resolves to true if an update was needed.
     */
    async checkEmployees(): Promise<boolean>{
        const entities: EmployeeEntity[] = await this.apiRepository.getEmployees();
        const isEqual: boolean = EmployeeEntity.compareTwoLists(this._employees,
            entities
        );
        this._employees = [...entities];
        return !isEqual;
    }
}
wet flax
#

Could it be a different test that's causing this log to pirnt?

pliant rain
#

import { Injectable, OnModuleInit } from '@nestjs/common';
import { TokenService } from "../token/token.service";
import axios from "axios";
import { formatDate } from "../utils/utils";
import { EmployeeModel } from "../employees/models/employee.model";
import { EmployeeEntity } from "../employees/entities/employees.entity";

@Injectable()
export class ApiRepository implements OnModuleInit {
    constructor(private readonly tokenService: TokenService,){
    }

    {Functions that call rest api}
    async onModuleInit(): Promise<void>{
        await this.tokenService.fetchToken();
    }
}
#

ah sorry i made a change since i posted and forgot to update the code here, yes you are right the test thats failing is:

describe('checkEmployees',
            () => {
                it('should return true when an update is needed',
                    async () => {
                        const result = await employeesService.checkEmployees();
                        expect(result).toBe(true);
                        expect(apiRepository.getEmployees).toHaveBeenCalledWith(
                        );
                    }
                );
            }
        )
wet flax
#

Are you using jest or vitest?

pliant rain
#

jest

wet flax
#

Then from what I can see, everything looks fine, and to debug anymore I'd need a reproduction

pliant rain
#

Can i give you one tomorrow?

#

dont think i will manage that today

wet flax
#

That's fine

pliant rain
#

@wet flax
I made new nx monorepo (since its the one im using) and tested a couple of stuff:
even when i copy the whole app and put it in the new monorepo the test actually passes, and ApiRepository mock is being injected correctly
what can cause the issue?

#

oh the problem is in tsconfig.base.json

#

i had emitDecoratorMetadata set to false which for some reason broke it

wet flax
#

Glad you were able to find it. That metadata is what nest needs to be figured out what to inject