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
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