NestJS integration tests are failing due to an undefined Custom TypeORM Repository

I am currently facing a challenge while writing integration tests for my Nest.js application. The custom TypeORM repositories in my test context are being marked as undefined. This issue may be occurring because I am not utilizing @InjectRepository. Instead, I have created request-scoped injectables that extend a BaseRepository to handle transactions within my requests. (I establish and manage one transaction per request, handling commit/rollback operations using interceptors. For more details on this approach, refer to the following article: https://medium.com/@dev.muhammet.ozen/advanced-transaction-management-with-nestjs-typeorm-43a839363491)

import { Test, TestingModule } from '@nestjs/testing';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ProductService } from '../../src/modules/product/product.service';
import { ProductRepository } from '../../src/repositories/product.repository';

describe('ProductService (integration)', () => {
  let productService: ProductService;
  let productRepo: ProductRepository;

  beforeAll(async () => {
    const module: TestingModule = await Test.createTestingModule({
      imports: [
        TypeOrmModule.forRoot({
          type: 'postgres',
          url: process.env.TEST_DB_URL,
          migrationsRun: true,
          logging: false,
          migrations: [__dirname + '/../../src/migrations/**/*{.ts,.js}'],
          entities: [__dirname + '/../../src/entities/*.entity{.ts,.js}'],
        }),
      ],
      providers: [
        ProductRepository,
        ProductService,
      ],
    }).compile();

    productService = module.get<ProductService>(ProductService);
    productRepo = await module.resolve(ProductRepository);
  });

  it('repo test', async () => {
    const result = await productService.getProductByName('randomName');
    expect(result).toBeNull();
  });
});
import { Injectable } from '@nestjs/common';
import { ProductEntity } from '../../entities/product.entity';
import { ProductRepository } from '../../repositories/product.repository';

@Injectable()
export class ProductService {
  constructor(
    private readonly productRepo: ProductRepository,
  ) {}

  async getProductByName(name: string): Promise<ProductEntity> {
    const product = await this.productRepo.getRepository().findOne({ where: { name: name } });
    return product;
  }
}

Now, diving into the repository:

import { Request } from 'express';
import { DataSource, EntityManager, Repository } from 'typeorm';
import { ENTITY_MANAGER_KEY } from '../utils/consts';

export class BaseRepository {
  constructor(
    private dataSource: DataSource,
    private request: Request,
  ) {}

  protected getRepository<T>(entityClass: new () => T): Repository<T> {
    const entityManager: EntityManager = this.request
      ? this.request[ENTITY_MANAGER_KEY] ?? this.dataSource.manager
      : this.dataSource.manager;

    return entityManager.getRepository(entityClass);
  }
}
import { Inject, Injectable, Scope } from '@nestjs/common';
import { REQUEST } from '@nestjs/core';
import { Request } from 'express';
import { DataSource, Repository } from 'typeorm';
import { ProductEntity } from '../entities/product.entity';
import { BaseRepository } from './baseRepository';

@Injectable({ scope: Scope.REQUEST })
export class ProductRepository extends BaseRepository {
  constructor(dataSource: DataSource, @Inject(REQUEST) req: Request) {
    super(dataSource, req);
  }

  getRepository(): Repository<ProductEntity>;
  getRepository<T>(entityClass: new () => T): Repository<T>;
  getRepository<T>(entityClass?: new () => T | ProductEntity): Repository<T | ProductEntity> {
    if (entityClass === undefined) {
      return super.getRepository(ProductEntity);
    }

    return super.getRepository(entityClass);
  }
}

Upon running the test, I encountered the following error:

TypeError: Cannot read properties of undefined (reading 'getRepository')

The productRepo within ProductService.getProductByName remains undefined. I have experimented with changing the scope to default, but this did not resolve the issue.

Interestingly, when I adjusted the test to directly use the repository provided within the TestingModule, it worked as expected:

  it('test repo', async () => {
    const result = await productRepo.getRepository().findOne({ where: { name: 'randomName' } });
    expect(result).toBeNull();
  });

I would appreciate any insights or guidance on solving this issue.

Answer №1

After some investigation, it became clear that utilizing resolve for ProductService was necessary. This is because it is not a singleton, as it relies on a request scoped provider.

productService = module.get<ProductService>(ProductService);

can be replaced with

productService = await module.resolve(ProductService);

The challenge was discussed within NestJS's repository: https://github.com/nestjs/nest/issues/13095

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

Is it possible for Next.js to retrieve the window size without resorting to a faulty hook call or encountering an undefined window

In my ongoing efforts to dynamically adjust the size of an image within a next.js application to make it responsive to various screen sizes, I have encountered challenges. The different methods I have attempted and observed have resulted in either an inv ...

Encountering issues with Proxy functionality in the latest versions of Angular 13 and Spring Boot

I've encountered an issue with the proxy configuration in Angular. I'm unsure if it's a problem within my Angular settings or if there's a configuration issue in Spring. For testing purposes, I have a backend built in springboot to han ...

Leverage data from viewing the page source within an automated testing environment

Trying to extract information from my page source for automated tests on every release. However, I want to avoid manually updating the release number as I integrate my tests into CI. Is there a way to pull the tag from the page source? All I've mana ...

Issue with Mockjax: asynchronous form submissions are not being intercepted

Currently, I am facing an issue while using qUnit and mockjax to handle a basic async form submission. It seems like the async POST request is passing through mockjax for some reason. test 'RuleModal closes the modal on a successful form submission e ...

Is it possible to turn off Angular CLI ng build linting for a specific directory?

I am facing an issue with a specific directory in my project template that I want to exclude from linting. Despite excluding it in both tsconfig and eslint, running eslint works fine but when using ng build, the directory is still included in linting and e ...

Troubleshooting compilation problems in Angular2 with nested components

I have created two components in Angular2 using TypeScript: app/app.component.ts import { Component } from '@angular/core'; @Component({ selector: 'my-app', styles : [` .parent { background : #c7c7c7; ...

Testing React Hook Form always returns false for the "isValid" property

When creating a registration modal screen, I encountered an issue with the isValid value when submitting the form. In my local environment (launched by npm start), the isValid value functions correctly without any issues. However, during unit testing us ...

detect the dismissal event in the modal controller from the main component

Within my MainPage, I invoke the create function in the ModalController, which displays the ModalPage. Upon clicking cancel, the dismiss function is called and we are returned to the MainPage. The process functions as expected. @Component({ selector: &a ...

The 'ReactNode' binding element is automatically assigned an 'any' type

Just started a new project using create-react-app app --template typescript. In the src/components/MyButton/MyButton.tsx file, I have the following code: import React, { ReactNode } from "react"; const MyButton = ({ children: ReactNode }) => ...

New to React and struggling with updating the DOM

Upon receiving a React project, I am faced with the task of performing a complex state update on my DOM. Here is how my component looks: /** @jsx jsx */ import { jsx } from '@emotion/core'; import { Typography } from '@material-ui/core&ap ...

Receiving error in TypeScript while using the 'required' attribute in the input field: "Cannot assign type 'string | undefined' to parameter expecting type 'string'"

In my TypeScript code, I am currently in the process of transitioning from utilizing useState to useRef for capturing text input values. This change is recommended when no additional manipulation necessitating state or rerenders is required. While I have ...

When running tests on Angular components that interact with Firebase, errors occur, specifically in the creation phase, resulting in a NullInjectionError. However

Currently, I am in the final stages of developing a chat application using Angular and Firebase. Everything appears to be working smoothly until I encountered numerous strange errors during testing. One particular issue is the inability to create certain ...

The Next.js build encountered an error - unable to locate function in next/script module

While constructing a CMS using next.js, one of the key components is media management through Cloudinary. The integration of the Cloudinary Media Library widget was successful during development using next/script. However, an error has now emerged that pre ...

Encountering an issue while trying to utilize Vuex in Vue with TypeScript

I recently utilized npm to install both vue (2.4.2) and vuex (2.3.1). However, when attempting to compile the following code snippet, I encountered the following error: https://i.stack.imgur.com/0ZKgE.png Store.ts import Vue from 'vue'; import ...

What methods can you use to identify obsolete or inactive code within an Angular project?

For over a year, my team and I have been dedicated to developing an innovative angular application. As we engage in the ongoing process of code refactoring, our objective is to eliminate any unnecessary or obsolete code from our repository. We are seeking ...

Manipulating variables across various methods in TypeScript

I have a simple code snippet where two variables are defined in the Main method and I need to access them from another method. However, I am encountering an issue with 'variables are not defined', even though I specified them in the declerations ...

What is the process of converting the Object type returned from an Observable to an array of objects in Angular?

When utilizing the GET method to retrieve information, I have encountered a problem. Here is the code snippet: constructor(private http: HttpClient) { } items: Item[]; stuff: any[]; ngOnInit() { const url = ...; this.http.get(url) .subscribe(nex ...

Sorting an object array by date is causing a problem

UPDATE: Finally cracked the code on this issue. I initially assumed that Date was interpreting the date ("29-04-2020") as DD-MM-YYYY, when it should actually be MM-DD-YYYY. For instance, here's an object array I'm working with: let t ...

Utilizing an array of data to create a complex structure with nested

In my Next.JS React project using TSX files, I have set up a data file like this: const fieldMapping = { category:[ { title: "Category 1", Subtitle: ["Category 1", "Category 2"], SubSubTitle: ["Category ...

Angular2: Exploring the Differences Between Observable.fromEvent and Button Click

As I work with my code, I have noticed that I am using both <button (click)="callsomefucntion" /> and Observable.fromEvent<MouseEvent>(button.nativeElement.'click') interchangeably. I am curious to understand the distinction between ...