35

i need help with nestjs and jest testing. I am new to NestJS and i got stuck on Cannot find module error when i run tests.

I am trying to test my service and when i run tests i have received error message:

src/article/article.service.spec.ts ● Test suite failed to run

Cannot find module 'src/article/article.entity' from 'comment/comment.entity.ts'

Require stack:
  comment/comment.entity.ts
  article/article.entity.ts
  article/article.service.spec.ts

   6 |   ManyToOne,
   7 | } from 'typeorm';
>  8 | import { Article } from 'src/article/article.entity';
     | ^
   9 | 
  10 | @Entity()
  11 | export class Comment {

  at Resolver.resolveModule (../node_modules/jest-resolve/build/index.js:307:11)
  at Object.<anonymous> (comment/comment.entity.ts:8:1)

This similiar error is showing up through all other tests in different controllers, services etc.

There is my code what i am trying to test.

article.service.ts

import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Article } from "./article.entity";
import { ArticleRepository } from "./article.repository";
import { ArticleDTO } from "./dto/article.dto";
import { DeleteResult } from "typeorm";
import { ArticleRO } from "./dto/article.response";
import { UserRepository } from "src/user/user.repository";

@Injectable()
export class ArticleService {
  constructor(
    private readonly articleRepository: ArticleRepository,
    private readonly userRepository: UserRepository
  ) {}

  async getAllPosts(): Promise<ArticleRO[]> {
    return await this.articleRepository.find();
  }
}

article.repository.ts

import { Repository, EntityRepository } from 'typeorm';
import { Article } from './article.entity';
@EntityRepository(Article)
export class ArticleRepository extends Repository<Article> {
}

article.service.specs.ts

import { Test, TestingModule } from "@nestjs/testing";
import { getRepositoryToken } from "@nestjs/typeorm";
import { Article } from "./article.entity";
import { ArticleRepository } from "./article.repository";
import { ArticleService } from "./article.service";
import { ArticleRO } from "./dto/article.response";

describe("PostService", () => {
  let service: ArticleService;
  let articleRepository: ArticleRepository;
  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        ArticleService,
        {
          provide: getRepositoryToken(Article),
          useClass: ArticleRepository,
        },
      ],
    }).compile();

    service = module.get<ArticleService>(ArticleService);
    articleRepository = module.get<ArticleRepository>(
      getRepositoryToken(Article)
    );
  });

  it("should be defined", () => {
    expect(service).toBeDefined();
  });
  describe("findAll", () => {
    it("should return an array of cats", async () => {
      const result: ArticleRO[] = [];
      jest.spyOn(service, "getAllPosts").mockResolvedValueOnce(result);

      expect(await service.getAllPosts()).toBe(result);
    });
  });
});


comment.entity.ts

import {
  Entity,
  Column,
  PrimaryGeneratedColumn,
  CreateDateColumn,
  ManyToOne,
} from 'typeorm';
import { Article } from 'src/article/article.entity';

@Entity()
export class Comment {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  author: string;

  @Column()
  content: string;

  @CreateDateColumn()
  createdAt: Date;

  @ManyToOne(
    () => Article,
    article => article.comments,
  )
  article: Article;
}

there are my jest settings from package.json.

"jest": {
    "moduleFileExtensions": [
      "js",
      "json",
      "ts"
    ],
    "rootDir": "src",
    "testRegex": ".spec.ts$",
    "transform": {
      "^.+\\.(t|j)s$": "ts-jest"
    },
    "coverageDirectory": "../coverage",
    "testEnvironment": "node"
  }

I tried to change my rootDir to "./src" but this does not work.

I generated project with nest new blabla. So my jest settings are default. Maybe i am doing something wrong with my custom repository mocking in tests.

Dobby Dimov
  • 944
  • 8
  • 10
Ergeros
  • 361
  • 1
  • 3
  • 6

6 Answers6

52

You can tell Jest how to resolve module paths by configuring the moduleNameMapper option, which is useful if you're using packages like module-alias or if you're using absolute paths. Add these lines to your Jest configuration:

{
  // ...

  "jest": {
    // ...

    "moduleNameMapper": {
      "^src/(.*)$": "<rootDir>/$1"
    }
  }
}

Now modules that start with src/ will be looked into <rootDir>/, which is the src folder by default (this configured a few lines above). Check out the documentation link above to get ideas of everything you can do with this.

I don't know what's wrong with using absolute paths as the other reply said, it's not only useful but it also works just fine in both NestJS and in Angular.

Parziphal
  • 6,222
  • 4
  • 34
  • 36
  • 3
    That snippet wouldn't work, it has to specify the actual `path` again when mapped like `"^src/(.*)$": "/src/$1"` works for me ! – ANUBIS Jun 14 '21 at 12:50
  • @ANUBIS FWIW, your suggestion didn't work me, but Parziphal worked fine. – titusmagnus Oct 22 '22 at 00:20
  • 3
    I already had this in my jest section in package.json in project root but that wasn't being picked up for me - had to add it to test/jest-e2e.json slightly modified as ```"^src/(.*)": "/../src/$1"``` – Dave Amphlett Oct 25 '22 at 13:40
  • can someone explain the role of using ```$1``` here – m-ketan Apr 25 '23 at 09:50
  • 1
    @m-ketan the regex `src/(.*)$` is matching everything after `src/` and stores it in a "variable" that can be used in the replacement, e.g. `src/foobar` becomes `/foobar`. Google "regex numbered backreference" for more info. – Parziphal Apr 25 '23 at 21:51
45

don´t use paths like "src/article/article.entity" in your app, these are not available after compile. Instead take relative paths like "../../article/article.entity" (this is just a guessed path)...Regards

dombre77
  • 491
  • 3
  • 2
19

Changing To Relative Imports

And the VSCode setting to automate that.

I had to change my VSCode import settings to use relative paths for TypeScript. By default, VSCode was importing with "shortest" path, which looked like src/auth/user.entity. My NestJS app was compiling fine, but I was getting the same Jest testing errors as you.

After changing setting TypeScript › Preferences: Import Module Specifier to relative, the modules are importing like ../auth/user.entity. (Ensure you're changing the setting for TypeScript, as there is an identical setting for JavaScript. I changed both.).

Making these module import changes fixed my NestJS Jest testing issues, with similar Cannot find module 'src/article/article.entity' from 'comment/comment.entity.ts' style errors.

More details about changing the VSCode typescript preferences are here: https://stackoverflow.com/a/53137571/8177355

Matthew Rideout
  • 7,330
  • 2
  • 42
  • 61
  • @dombre77 answer solves the problem and the reason for those imports to be different was this vscode config. Also, probably this can be sorted on Jest side as mentioned by others by changing its config – Danilo Marques Sep 28 '22 at 12:28
4

I had the same issue but was solved by adding these lines of code in /test/jest-e2e.json

  "moduleNameMapper": {
    "^src/(.*)": "<rootDir>/../src/$1"
  }
Mistico
  • 231
  • 3
  • 4
2

Relative import instead of absolute!!!

For example: enter image description here

import { AppModule } from '../src/app.module';
0

right click on the file and click "Copy Relavant Path" and paste and remove file extension

ex:

import { function_name } from '/paste full relevant path to here and remove extenstion'
BIS Tech
  • 17,000
  • 12
  • 99
  • 148