Search code examples
jestjsnestjsnest

NestJS Nest can't resolve dependencies of the UserService (?). [...] argument dependency at index [0] is available in the RootTestModule context


I am trying to write tests for my NestJS app. It as several services, including AuthService and UserService.

I managed to write tests for the AuthService :

auth.service.spec.ts

import { JwtService } from '@nestjs/jwt';
import { Test } from '@nestjs/testing';

import { AuthService } from '../../src/modules/auth/auth.service';
import { UserService } from '../../src/modules/user';

describe('AuthService', () => {
  let authService: AuthService;

  const mockJwtService = {};

  const mockUserService = {
    getAll: jest.fn(),
    getUnique: jest.fn(),
    createUser: jest.fn(),
  };

  beforeEach(async () => {
    // initialize a NestJS module with authService
    const module = await Test.createTestingModule({
      providers: [
        AuthService,
        {
          provide: JwtService,
          useValue: mockJwtService,
        },
        {
          provide: UserService,
          useValue: mockUserService,
        },
      ],
    }).compile();

    authService = module.get(AuthService);
  });

  // it = "test case"
  it('should be defined', () => {
    expect(authService).toBeDefined();
  });

... // MORE TESTS

});

auth.service.ts :

import { Injectable, Logger, NotFoundException } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { User } from '@prisma/client';
import axios from 'axios';

import { UserService } from '../user';
import { FortyTwoProfile, JwtPayload } from './auth.interface';

@Injectable()
export class AuthService {
  private readonly logger = new Logger(AuthService.name);

  constructor(
    private jwtService: JwtService,
    private userService: UserService,
  ) {}


... // Some functions

}

But I am stuck on writing tests for the user.service.ts :

user.service.spec.ts :

import { Test, TestingModule } from '@nestjs/testing';
import { Prisma, PrismaClient } from '@prisma/client';
import { DeepMockProxy, mockDeep } from 'jest-mock-extended';
import { PrismaService } from 'nestjs-prisma';

import { UserService } from '../../src/modules/user/user.service';

describe('UserService', () => {
  let user: UserService;
  let prisma: DeepMockProxy<PrismaClient>;

  beforeEach(async () => {
    // initialize a NestJS module with userService
    const module: TestingModule = await Test.createTestingModule({
      providers: [UserService, { provide: PrismaService, useValue: jest.fn() }],
    })
      .overrideProvider(PrismaService)
      .useValue(mockDeep<PrismaClient>())
      .compile();

    user = module.get(UserService);
    prisma = module.get(PrismaService);
  });

... // MORE TESTS

});

user.service.ts :

import { Injectable, NotFoundException } from '@nestjs/common';
import { User } from '@prisma/client';

import { PrismaService } from '@/prisma';

import { FortyTwoProfile } from '../auth';

@Injectable()
export class UserService {
  constructor(private prisma: PrismaService) {}

  async getAll(): Promise<User[]> {
    return this.prisma.user.findMany();
  }

... // MORE FUNCTIONS
}

Here is my tree :

├── prisma
│   ├── index.ts
│   ├── migrations
│   │   ├── 20230822155638_init
│   │   │   └── migration.sql
│   │   └── migration_lock.toml
│   └── schema.prisma
├── src
│   ├── app.middleware.ts
│   ├── app.module.ts
│   ├── config.ts
│   ├── main.ts
│   ├── modules
│   │   ├── auth
│   │   │   ├── auth.controller.ts
│   │   │   ├── auth.interface.ts
│   │   │   ├── auth.module.ts
│   │   │   ├── auth.service.ts
│   │   │   ├── ...
│   │   ├── ...
│   │   └── user
│   │       ├── index.ts
│   │       ├── user.controller.ts
│   │       ├── user.module.ts
│   │       └── user.service.ts
│   └── prisma
│       ├── index.ts
│       └── prisma.service.ts
├── test
│   ├── auth
│   │   └── auth.service.spec.ts
│   ├── jest.config.json
│   └── user
│       └── user.service.spec.ts
├── tsconfig.build.json
└── tsconfig.json

I am getting this error :


  ● UserService › should be defined

    Nest can't resolve dependencies of the UserService (?). Please make sure that the argument dependency at index [0] is available in the RootTestModule context.

    Potential solutions:
    - Is RootTestModule a valid NestJS module?
    - If dependency is a provider, is it part of the current RootTestModule?
    - If dependency is exported from a separate @Module, is that module imported within RootTestModule?
      @Module({
        imports: [ /* the Module containing dependency */ ]
      })

      12 |   beforeEach(async () => {
      13 |     // initialize a NestJS module with userService
    > 14 |     const module: TestingModule = await Test.createTestingModule({
         |                                   ^
      15 |       providers: [UserService, { provide: PrismaService, useValue: jest.fn() }],
      16 |     })
      17 |       .overrideProvider(PrismaService)

Thank your help, and sorry if I gave too much information, this is my first question on StackOverflow.

Cheers,

I trie to replace { provide: PrismaService, useValue: jest.fn() } by PrismaService.

I tried to test only UserService and not AuthService,

I tried many of those solutions : Testing a NestJS Service that uses Prisma without actually accessing the database


UPDATE 1 :

Here is the prisma.service.ts file :

import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';

@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
  async onModuleInit() {
    await this.$connect();
    Logger.log('Prisma connected', 'PrismaService');
  }
}

And the schema.prisma :

generator client {
    provider = "prisma-client-js"
}

datasource db {
    provider = "postgresql"
    url      = env("DATABASE_URL")
}

model User {
    id          String   @id @default(uuid())
    login       String   @unique
    email       String   @unique
    imageUrl    String?
    displayName String
    firstName   String
    lastName    String
    createdAt   DateTime @default(now())
}

UPDATE 2 :

Here is my jest.config.json :

{
  "moduleFileExtensions": ["js", "json", "ts"],
  "rootDir": ".",
  "testEnvironment": "node",
  "testRegex": ".e2e-spec.ts$",
  "testMatch": ["<rootDir>/src/**/*spec.ts"],
  "transform": {
    "^.+\\.(t|j)s$": "ts-jest"
  },
  "collectCoverage": true,
  "moduleNameMapper": {
    "^@/(.*)$": "<rootDir>/src/$1"
  }
}

UPDATE 3 :

You can reproduce the problem here : https://github.com/B-ki/bug_nest


Solution

  • Your moduleNameMapper in the package.json should be <rootDir>/src/$1. Just <rootdir>/$1 was resolving to ./prisma which would import ./primsa/index.ts which didn't have the value Nest needed to resolve. You were meaning to import ./src/prisma, hence the need to add the src to the moduleNameMapper's configuration