Nest JS: Encounterment of undefined properties in repository during test execution

I encountered an issue where I am unable to access the repository in my test. It appears that the repository is not being injected during the test. Below is the code snippet I used:

ads.module.ts

@Module({
  imports: [
    TypeOrmModule.forFeature([Ads]),
    ProfilesModule,
  ],
  providers: [AdsService],
  controllers: [AdsController],
  exports: [AdsService],
})
export class AdsModule {}

profile.module.ts

@Module({
  imports: [
    TypeOrmModule.forFeature([Profiles]),
  ],
  providers: [ProfilesService],
  controllers: [ProfilesController],
  exports: [ProfilesService],
})
export class ProfilesModule {}

ads.service.ts

@Injectable()
export class AdsService {
  constructor(
    @InjectRepository(Ads) private adsRepository: Repository<Ads>,
    private profileService: ProfilesService,
  ) {}

  create = async (createAdsDto: AdsDto) => {
    const profile = await this.profileService.findByProfileId(
      createAdsDto.profileId,
    ); 

    return null;
  }
}

profiles.service.ts

@Injectable()
export class ProfilesService {
  constructor(
    @InjectRepository(Profiles) private profileRepository: Repository<Profiles>
  ) {}

  findByProfileId = async (id: number): Promise<Profiles> => {
    // below line is failing
    const profile = await this.profileRepository.findOne({
      where: { id },
      relations: { user: true, avatar: true },
    });

    return profile;
  };
}

ads.service.spec.ts

describe('AdsService', () => {
  let service: AdsService;
  let adsRepository: Repository<Ads>;
  let profileRepository: Repository<Profiles>;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        AdsService,
        { 
          provide: getRepositoryToken(Ads), 
          useClass: Repository 
        },
        ProfilesService,
        { 
          provide: getRepositoryToken(Profiles), 
          useClass: Repository 
        },
      ],
    }).compile();

    service = module.get(AdsService);
    adsRepository = module.get<Repository<Ads>>(getRepositoryToken(Ads));
    profileRepository = module.get<Repository<Profiles>>(
      getRepositoryToken(Profiles),
    );
  });

  afterAll(() => {
    jest.resetAllMocks();
  });

  describe('Initial variables must be defined', () => {
    test('Ads Service must be defined', () => {
      expect(service).toBeDefined();
    });

    test('Ads Repository must be defined', () => {
      expect(adsRepository).toBeDefined();
    });

    test('Profile Repository must be defined', () => {
      expect(profileRepository).toBeDefined();
    });

    test('can create ads', async () => {
      const ads = await service.create({
        profileId: 1,
        type: 'Oferta',
        category: 'Vivienda',
        location: 'Alicante',
        title: 'Apartment For Rent',
        description: 'This is a sample description',
        extract: 'This is a sample extract short description',
      } as AdsDto);
    });
  });
});

The failure seems to be related to the profile service's inability to inject the repository during the test. Here is a screenshot of the test result:

https://i.sstatic.net/KrclZ.png

Answer №1

Are you looking to simulate the repository or use an actual one? When it comes to unit tests, it's typically best to simulate it. I'll explain both scenarios.

Simulated Repository

To create a simulated Repository, start by creating a mock object:

export const createRepositoryMock = (): Repository => {
  const repositoryMock = <Repository>Object.getOwnPropertyNames(Repository.prototype).reduce((acc, x) => {
    acc[x] = jest.fn();
    return acc;
  }, {});
  return repositoryMock;
};

Then in your test file, utilize this mock object.

describe('Test', () => {
  let repo: Repository<Ads>;

  beforeEach(async () => {
    const app: TestingModule = await Test.createTestingModule({
      providers: [
        { provide: getRepositoryToken(Ads), useValue: createRepositoryMock() },
      ],
    });
  });
  repo = app.get<Repository<Ads>>(getRepositoryToken(Ads));
});

In this way, all functions are mocked using jest.fn(), allowing you to then use them with jest.spyOn() to implement your own versions.

describe('test repo', () => {
  it('tests find function', async () => {
    jest.spyOn(repo, 'findOne').mockResolvedValueOnce({ a: 123, b: 'c' });
    console.log(repo.findOne());
  });
});

Actual Repository

You need to include TypeOrmModule.forRoot in the test module for this scenario.

describe('Test', () => {
  let repo: Repository<Ads>;

  beforeEach(async () => {
    const app: TestingModule = await Test.createTestingModule({
      imports: [TypeOrmModule.forRoot()],
      providers: [
        { provide: getRepositoryToken(Ads), useValue: Repository<Ads> },
      ],
    });
  });
  repo = app.get<Repository<Ads>>(getRepositoryToken(Ads));
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Having difficulty setting custom icons for clustering in Google Maps MarkerClusterer due to the absence of position data

I am struggling to understand the documentation for this utility. It seems that to customize cluster icons, I need to convert the cluster icon to a marker using the MarkerClusterer's renderer property and then apply icon styles as if it were a normal ...

This function CameraPreview.takePicture() does not have a return value

Recently, I've been working on updating an old app that was using an outdated version of the camera-preview plugin. The previous version had a method called setOnPictureTakenHandler which allowed me to easily retrieve the image URL. However, the new ...

Sequelize is not giving the expected model even after utilizing `include: [{ model: this.buildModel, required: true }]`

I've hit a roadblock trying to solve this problem. Despite my belief that I've correctly handled the migration, model definition, and query, I'm unable to retrieve the build in my iteration. Below are the models: SequelizeBuildModel.ts @Ta ...

Encountering an error in Angular2 and TypeScript: TS2322 error message stating that the type 'Response' cannot be assigned to type 'UserStatus'

Currently, I am facing some challenges while working with Angular2 and TypeScript. Transitioning from AngularJS to Angular2 has proven to be a bit tricky for me. To better understand this new framework, I decided to create an experimental app with the foll ...

If the input meets the requirements of the generic type, then it will be returned; otherwise, it

Currently, I am working on creating a filter function that takes a generic parameter and ensures that the return type of the given function is either the input if it matches the generic or null if it does not. type A = { type: 'A' }; type B = { t ...

Tips for integrating a variety of components onto a single webpage

Exploring the functionality of Angular, I am looking to include multiple components on a single page. How can this be achieved effectively in Angular? I envision each div representing a distinct component and view, with all components residing in separate ...

I am looking to update Vue.js 3's reactive values by utilizing a method implemented in an external file

Exploring how to update reactive values in Vue.js 3 using a method from an external file. Currently experimenting with Vue.js 3, I am looking to pass reactive values to a method defined in an external file for updating purposes. During the testing phase ...

Contrasting {} and {} as any in TypeScript

Seeking clarity on TypeScript, what sets apart (foo and foo2) from (foo3 and foo4)? (foo and foo2) as well as (foo3 and foo4) produce identical results, yet during compilation, a red underline appears under foo2 and foo3. https://i.stack.imgur.com/lWaHc. ...

Obtain a distinct identifier for the present instance within TypeScript code for a multi-instance Node.js backend application

In our setup, we are running a Node.js application on Kubernetes with auto-scaling enabled. I need to log specific information related to the current instance, such as the pod name or IP address. Is there a way in Node.js and Typescript to retrieve such ...

Retrieving the value of a selected option in Angular

I have the following dropdown select in my HTML and I am currently retrieving the text content of the selected option. How can I access the value attribute instead? Here is the dropdown select: <form [formGroup]="angForm" class="form-inline my-5 my-l ...

Could you clarify the significance of the brackets in this TypeScript Lambda Expression?

I'm currently delving into an Angular book, but I'm struggling to locate any definitive documentation regarding the usage of square brackets in a lambda expression like [hours, rate]) => this.total = hours * rate. While I grasp that these para ...

``Using backticks to denote HTML syntax - Leveraging Google Charts to create

Has anyone found a way to incorporate HTML in ticks within a Google chart? I am attempting to insert a weather icon from This is my current attempt: const dailyData = new google.visualization.DataTable(); dailyData.addColumn('timeofday' ...

Keeping an Rxjs observable alive despite encountering errors by simply ignoring them

I am passing some values to an rxjs pipe and then subscribing to them. If there are any errors, I want to skip them and proceed with the remaining inputs. of('foo', 'bar', 'error', 'bazz', 'nar', 'erro ...

Response received through GET call in text format

Implementing a typed response in a simple GET request seems to be causing a strange behavior in the compiler. The application compiles successfully, but a red error is returned with the message displayed in the VS Code screenshot below: ERROR in src/app/s ...

Modifying tooltip format in React ApexChart from dots to commas

I am in the process of creating an app targeted towards German users, who traditionally use commas (20,00) instead of dots (20.00) for numbers. I am using react-apexcharts and struggling to figure out how to replace the dots with commas in both my chart an ...

Angular: Exploring the possibilities of condition-based click event implementation

In my component, there are two elements: 'order information' and a 'datepicker'. When clicking on the component, it will display the order information. However, I want to prevent the click event from being triggered if the user clicks ...

Unable to modify the border-radius property of Material UI DatePicker

I'm having difficulties setting rounded borders for my DatePicker component from @mui/x-date-pickers and Material UI V5. Here is the intended look I am aiming for: https://i.stack.imgur.com/c1T8b.png I've tried using styled components from Mat ...

Issue: Multiplying values within an array in TypeScript requires that the left-hand side of the arithmetic operation must be of type 'any', 'number', or 'enum'

Having trouble with Typescript as I encounter this error message The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.ts(2362) Specifically facing issues when trying to multi ...

Forgetting to include property annotations for objects

I am attempting to create a localized strings object: const strings = { hello: { en: 'hello', pl: 'hej' }, bye: { en: 'bye', pl: 'pa' } } While this setup works and Intellisense shows availa ...

How is it possible that the whitelist in NestJs does not generate errors when using an incorrect

I am implementing a white list in my route's body validation to ensure that only data conforming to my model is accepted. If any parameter is sent that is not part of my model DTO, an error should be thrown. Here is my DTO: export class RegisterDTO ...