How to test Models (Mongoose) in a service (NestJS) with jest - node.js

I have a backend done with NestJS. In my service I inject two Mongoose Models. I use Jest to test the service.
Models are declared as is and injected into the module:
quizes.providers.ts
import { Connection } from 'mongoose';
import { QuizSchema } from './schemas/quiz.schema';
export const quizesProviders = [
{
provide: 'CLASS_MODEL',
useFactory: (connection: Connection) => connection.model('Quiz', QuizSchema),
inject: ['DATABASE_CONNECTION'],
},
];
users.providers.ts
import { Connection } from 'mongoose';
import { UserSchema } from './schemas/user.schema';
export const usersProviders = [
{
provide: 'USER_MODEL',
useFactory: (connection: Connection) => connection.model('User', UserSchema),
inject: ['DATABASE_CONNECTION'],
},
];
Example of module:
quizes.module.ts
import { Module } from '#nestjs/common';
import { QuizesController } from './quizes.controller';
import { QuizesService } from './quizes.service';
import { quizesProviders } from './quizes.providers';
import { usersProviders } from '../auth/users.providers';
import { DatabaseModule } from 'src/database.module';
import { AuthModule } from 'src/auth/auth.module';
#Module({
imports: [DatabaseModule, AuthModule],
controllers: [QuizesController],
providers: [QuizesService,
...quizesProviders, ...usersProviders]
})
export class QuizesModule {}
Then in my service, I inject models:
quizes.service.ts
#Injectable()
export class QuizesService {
constructor(
#Inject('CLASS_MODEL')
private classModel: Model<Quiz>,
#Inject('USER_MODEL')
private userModel: Model<User>
) {}
In my quizes.spec.ts (jest) I began to do things like that. It compiles but doesn't work:
import { Test } from '#nestjs/testing';
import * as mongoose from 'mongoose';
import { User } from 'src/auth/user.interface';
import { Quiz } from './quiz.interface';
import { databaseProviders } from '../database.providers';
const USER_MODEL:mongoose.Model<User> = mongoose.model('User', UserSchema);
const CLASS_MODEL:mongoose.Model<Quiz> = mongoose.model('Quiz', QuizSchema);
const mockingQuizModel = () => {
find: jest.fn()
}
const mockingUserModel = () => {
find: jest.fn()
}
const mockUser = {
username: 'Test user'
}
describe('QuizesService', () => {
let quizesService;
let userModel , classModel;
beforeEach(async () => {
const module = await Test.createTestingModule({
providers: [QuizesService, ...usersProviders, ...quizesProviders,...databaseProviders,
{provide: USER_MODEL, useFactory: mockingUserModel},
{provide: CLASS_MODEL, useFactory: mockingQuizModel},
],
}).compile();
quizesService = await module.get<QuizesService>(QuizesService);
classModel = await module.get<mongoose.Model<Quiz>>(CLASS_MODEL)
userModel = await module.get<mongoose.Model<User>>(USER_MODEL)
})
describe('getAllQuizes', ()=> {
it('get all quizes', () => {
expect(userModel.find).not.toHaveBeenCalled();
})
})
})
userModel is undefined and the test does not exit.

Use the getModelToken function as defined in NestJS official: https://docs.nestjs.com/v6/
Techniques -> Mongo (Scroll down to Testing section)
Then your code should look a bit like this:
import { getModelToken } from '#nestjs/mongoose';
const mockRepository = {
find() {
return {};
}
};
const module = await Test.createTestingModule({
providers: [ ...,
{provide: getModelToken('CLASS_MODEL'), useValue: mockRepository,},
{provide: getModelToken('USER_MODEL'), useValue: mockRepository,},
],
...

Fixed
You should not use await for module.get
quizesService = module.get<QuizesService>(QuizesService);
clientClassModel = module.get(getModelToken('CLASS_MODEL'))
clientUserModel = module.get(getModelToken('USER_MODEL'))

The setup of the test suite was ok but not the test
I test the service getAllQuizes method
Here is the service
#Injectable()
export class QuizesService {
constructor(
#InjectModel('CLASS_MODEL')
private classModel: Model<Quiz>,
#InjectModel('USER_MODEL')
private userModel: Model<User>
) {}
async getAllQuizes(user: User) : Promise<Quiz[]> {
// console.log(user);
let userId;
try {
const userEntity = await this.userModel.find({username: user.username}).exec();
userId = userEntity[0]._id;
} catch (error) {
throw new NotFoundException('user not found');
}
return await this.classModel.find({user: userId}).exec();
}
Here is the test
it('get all quizes', async () => {
clientUserModel.find.mockResolvedValue('user1');
clientClassModel.find.mockResolvedValue([{title: 'test', description: 'test'}])
expect(clientUserModel.find).not.toHaveBeenCalled();
expect(clientClassModel.find).not.toHaveBeenCalled();
const result = quizesService.getAllQuizes(mockUser);
expect(clientUserModel.find).toHaveBeenCalled();
expect(clientClassModel.find).toHaveBeenCalled();
expect(result).toEqual([{title: 'test', description: 'test'}]);
})
My test is false because the assertion expect(clientClassModel.find).toHaveBeenCalled() is false
Whereas in my service I have a first call on find method of the user model, and a second call on the find method of the class model

Finally tests pass
describe("getAllQuizes", () => {
it("get all quizes, user not found", async () => {
clientUserModel.find.mockRejectedValue("user not found");
clientClassModel.find.mockResolvedValue([
{ title: "test", description: "test" },
]);
expect(clientUserModel.find).not.toHaveBeenCalled();
expect(clientClassModel.find).not.toHaveBeenCalled();
const result = quizesService.getAllQuizes(mockUser).catch((err) => {
expect(err.message).toEqual("user not found");
});
expect(clientUserModel.find).toHaveBeenCalled();
});
it("get all quizes, find quizzes", async () => {
clientUserModel.find.mockReturnValue({
_id: "1234",
username: "Test user",
});
clientClassModel.find.mockResolvedValue([
{ title: "test", description: "test" },
]);
expect(clientUserModel.find).not.toHaveBeenCalled();
expect(clientClassModel.find).not.toHaveBeenCalled();
const result = quizesService.getAllQuizes(mockUser).then((state) => {
expect(clientUserModel.find).toHaveBeenCalled();
expect(clientClassModel.find).toHaveBeenCalled();
expect(state).toEqual([{ title: "test", description: "test" }]);
});
//
});
});

Related

JEST How to mock getManager().query from NestJS

Hi I'm trying to test my service but got stuck
import { HttpException, Injectable } from '#nestjs/common';
import { InjectRepository } from '#nestjs/typeorm';
import { getManager, Repository } from 'typeorm';
import { PointsEntity } from './entities/point_store.entity';
#Injectable()
export class PointStoreService {
constructor(
#InjectRepository(PointsEntity)
private readonly pointsRepository: Repository<PointsEntity>,
) {}
async searchPoints(startDate: Date, endDate: Date, userId: string) {
try {
return await getManager().query(`
SELECT * FROM points WHERE expire_at
BETWEEN '${startDate.toISOString()}' AND '${endDate.toISOString()}'
AND "userId"='${userId}'
`);
} catch (err) {
throw new HttpException(err.message, err.state ? err.state : 500);
}
}
}
This is my Service code. As you know there is only one method.
import { Test, TestingModule } from '#nestjs/testing';
import { getRepositoryToken } from '#nestjs/typeorm';
import * as typeorm from 'typeorm';
import { PointsEntity } from './entities/point_store.entity';
import { PointStoreService } from './point_store.service';
const mockPointsRepository = {
save: jest.fn(),
};
describe('PointStoreService', () => {
let service: PointStoreService;
let repository: typeorm.Repository<PointsEntity>;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
PointStoreService,
{
provide: getRepositoryToken(PointsEntity),
useValue: mockPointsRepository,
},
],
}).compile();
jest.resetModules(); // Most important - it clears the cache
service = module.get<PointStoreService>(PointStoreService);
repository = module.get(getRepositoryToken(PointsEntity));
});
it('should be defined', () => {
expect(service).toBeDefined();
});
describe('searchPoints', () => {
it('should searchPoints', async () => {
// can not mock getManager!!!
jest.spyOn(getManager, 'query');
});
});
});
Now I code this test case. 'should be defined' works fine. But after I try to test 'should searchPoints', I have no idea to mock it.
Is there a way to mock getManager().query()?
gitHub repository

How to mock Jest Redis in Nestjs

I'm working on NestJs application and wrote unit test for my authenticateUser function in user.service.ts.It's has pass in my local machine.but when I deployed it in to server and run unit test, i got an error Redis connection to 127.0.0.1:6379 failed - connect ECONNREFUSED.Seems like redis mock is not working.How should I mock redis and resolve this issue for working?
user.service.ts
async authenticateUser(authDto: AuthDTO): Promise<AuthResponse> {
try {
const userData = await this.userRepository.findOne({msisdn});
if(userData){
await this.redisCacheService.setCache(msisdn, userData);
}
} catch (error) {
console.log(error)
}
}
redisCache.service.ts
export class RedisCacheService {
constructor(
#Inject(CACHE_MANAGER) private readonly cache: Cache,
) {}
async setCache(key, value) {
await this.cache.set(key, value);
}
}
user.service.spec.ts
describe('Test User Service', () => {
let userRepository: Repository<UserEntity>;
let userService: UserService;
let redisCacheService: RedisCacheService;
let cacheManager: any;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
UserService,
UserEntity,
RedisCacheService,
{
provide: getRepositoryToken(UserEntity),
useClass: registeredApplicationRepositoryMockFactory,
},
],
imports: [CacheModule.register({})],
}).compile();
userService = module.get<UserService>(UserService);
userRepository = module.get<Repository<UserEntity>>(
getRepositoryToken(UserEntity),
);
redisCacheService = module.get<RedisCacheService>(RedisCacheService);
cacheManager = module.get<any>(CACHE_MANAGER);
});
it('authenticateUser should return success response', async () => {
const userEntity = { id: 1, name: 'abc', age: 25 };
const mockSuccessResponse = new AuthResponse(
HttpStatus.OK,
STRING.SUCCESS,
`${STRING.USER} ${STRING.AUTHENTICATE} ${STRING.SUCCESS}`,
{},
);
jest.spyOn(userRepository, 'findOne').mockResolvedValueOnce(userEntity);
jest.spyOn(redisCacheService, 'setCache').mockResolvedValueOnce(null);
expect(await userService.authenticateUser(mockAuthBody)).toEqual(mockSuccessResponse);
});
});
You can mock CACHE_MANAGER using a custom provider:
import { CACHE_MANAGER } from '#nestjs/common';
import { Cache } from 'cache-manager';
describe('AppService', () => {
let service: AppService;
let cache: Cache;
beforeEach(async () => {
const app = await Test.createTestingModule({
providers: [
AppService,
{
provide: CACHE_MANAGER,
useValue: {
get: () => 'any value',
set: () => jest.fn(),
},
},
],
})
.compile();
service = app.get<AppService>(AppService);
cache = app.get(CACHE_MANAGER);
});
// Then you can use jest.spyOn() to spy and mock
it(`should cache the value`, async () => {
const spy = jest.spyOn(cache, 'set');
await service.cacheSomething();
expect(spy).toHaveBeenCalledTimes(1);
expect(spy.mock.calls[0][0]).toEqual('key');
expect(spy.mock.calls[0][1]).toEqual('value');
});
it(`should get the value from cache`, async () => {
const spy = jest.spyOn(cache, 'get');
await service.getSomething();
expect(spy).toHaveBeenCalledTimes(1);
});
it(`should return the value from the cache`, async () => {
jest.spyOn(cache, 'get').mockResolvedValueOnce('value');
const res = await service.getSomething();
expect(res).toEqual('value');
}),
});
More details on Custom Providers: https://docs.nestjs.com/fundamentals/custom-providers
Two more things, for unit testing you shouldn't import modules but mock the dependencies instead. And as Daniel said, UserService is not using CACHE_MANAGER but RedisCacheService, so you should mock RedisCacheService.
Usually the best thing to do is to only provide the service you're testing and mock the dependencies.
in order to use the jest spy functions you need to return the jest function directly.
providers: [
AppService,
{
provide: CACHE_MANAGER,
useValue: {
get: () => 'any value',
set: jest.fn(),
},
},
],

Jest - testing sequelize with Nest.js

I'm testing a nest.js service, this method basically will receive a find method from sequelize:
...
import { Auth } from './../../modules/auth/entities/auth.entity';
import { Sequelize } from 'sequelize-typescript';
import { getModelToken } from '#nestjs/sequelize';
jest.mock('./../../modules/auth/auth.service');
const sequelize = new Sequelize({ validateOnly: true });
sequelize.addModels([Auth]);
const testAuth = new Auth({
id_user: '1',
});
describe('AuthGuardService', () => {
let service: AuthGuardService;
let authService: AuthService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
AuthGuardService,
AuthService,
{
provide: getModelToken(Auth),
useValue: { findOne: jest.fn(() => testAuth) },
},
],
imports: [HttpModule],
}).compile();
service = module.get<AuthGuardService>(AuthGuardService);
authService = module.get<AuthService>(AuthService);
});
...
it('it should return true', async () => {
expect(
await authService.find({
id: '1',
})
).toEqual(testAuth);
});
on my service I'm trying to test this exactly block:
const user = await this.authService.find({
id: value,
});
if(user.id === some_value) {
return true;
}
but I always get undefined when I tried to read user from my test.
TypeError: Cannot read property 'id' of undefined

How to change a Database connection dynamically with Request Scope Providers in Nestjs?

Working on a project with Nestjs 6.x, Mongoose, Mongo, etc...
Regarding to the Back End, in my use case, I must change the connection of one of my databases depending of some conditions/parameters coming from some requests.
Basically, I have this
mongoose.createConnection('mongodb://127.0.0.1/whatever-a', { useNewUrlParser: true })
and I want to change to, for example
mongoose.createConnection('mongodb://127.0.0.1/whatever-b', { useNewUrlParser: true })
Therefore, I have in Nestjs the first provider
export const databaseProviders = [
{
provide: 'DbConnectionToken',
useFactory: async (): Promise<typeof mongoose> =>
await mongoose.createConnection('mongodb://127.0.0.1/whatever', { useNewUrlParser: true })
}
I was researching for a while and I found out that in release Nestjs 6.x there are provider requests allowing me to modify dynamically Per-request the injection of some providers.
Anyway, I don't know how to achieve my change neither if it is going to be working in case I'd achieve that
Can anyone help or guide me?
Many thanks in advance.
You can do the following using Nest's built-in Mongoose package:
/*************************
* mognoose.service.ts
*************************/
import { Inject, Injectable, Scope } from '#nestjs/common';
import { MongooseOptionsFactory, MongooseModuleOptions } from '#nestjs/mongoose';
import { REQUEST } from '#nestjs/core';
import { Request } from '#nestjs/common';
#Injectable({ scope: Scope.REQUEST })
export class MongooseConfigService implements MongooseOptionsFactory {
constructor(
#Inject(REQUEST) private readonly request: Request,) {
}
createMongooseOptions(): MongooseModuleOptions {
return {
uri: request.params.uri, // Change this to whatever you want; you have full access to the request object.
};
}
}
/*************************
* mongoose.module.ts
*************************/
import { Module } from '#nestjs/common';
import { MongooseModule } from '#nestjs/mongoose';
import { MongooseConfigService } from 'mognoose.service';
#Module({
imports: [
MongooseModule.forRootAsync({
useClass: MongooseConfigService,
}),
]
})
export class DbModule {}
Then, you can attach whatever you want to the request and change the database per request; hence the use of the Scope.REQUEST. You can read more about Injection Scopes on their docs.
Edit: If you run into issues with PassportJS (or any other package) or the request is empty, it seems to be an error that relates to PassportJS (or the other package) not supporting request scopes; you may read more about the issue on GitHub regarding PassportJS.
I did a simple implementation for nest-mongodb,
The main changes are in mongo-core.module.ts where I store the connections in a map and used them if available instead of creating a new connection every time.
import {
Module,
Inject,
Global,
DynamicModule,
Provider,
OnModuleDestroy,
} from '#nestjs/common';
import { ModuleRef } from '#nestjs/core';
import { MongoClient, MongoClientOptions } from 'mongodb';
import {
DEFAULT_MONGO_CLIENT_OPTIONS,
MONGO_MODULE_OPTIONS,
DEFAULT_MONGO_CONTAINER_NAME,
MONGO_CONTAINER_NAME,
} from './mongo.constants';
import {
MongoModuleAsyncOptions,
MongoOptionsFactory,
MongoModuleOptions,
} from './interfaces';
import { getClientToken, getContainerToken, getDbToken } from './mongo.util';
import * as hash from 'object-hash';
#Global()
#Module({})
export class MongoCoreModule implements OnModuleDestroy {
constructor(
#Inject(MONGO_CONTAINER_NAME) private readonly containerName: string,
private readonly moduleRef: ModuleRef,
) {}
static forRoot(
uri: string,
dbName: string,
clientOptions: MongoClientOptions = DEFAULT_MONGO_CLIENT_OPTIONS,
containerName: string = DEFAULT_MONGO_CONTAINER_NAME,
): DynamicModule {
const containerNameProvider = {
provide: MONGO_CONTAINER_NAME,
useValue: containerName,
};
const connectionContainerProvider = {
provide: getContainerToken(containerName),
useFactory: () => new Map<any, MongoClient>(),
};
const clientProvider = {
provide: getClientToken(containerName),
useFactory: async (connections: Map<any, MongoClient>) => {
const key = hash.sha1({
uri: uri,
clientOptions: clientOptions,
});
if (connections.has(key)) {
return connections.get(key);
}
const client = new MongoClient(uri, clientOptions);
connections.set(key, client);
return await client.connect();
},
inject: [getContainerToken(containerName)],
};
const dbProvider = {
provide: getDbToken(containerName),
useFactory: (client: MongoClient) => client.db(dbName),
inject: [getClientToken(containerName)],
};
return {
module: MongoCoreModule,
providers: [
containerNameProvider,
connectionContainerProvider,
clientProvider,
dbProvider,
],
exports: [clientProvider, dbProvider],
};
}
static forRootAsync(options: MongoModuleAsyncOptions): DynamicModule {
const mongoContainerName =
options.containerName || DEFAULT_MONGO_CONTAINER_NAME;
const containerNameProvider = {
provide: MONGO_CONTAINER_NAME,
useValue: mongoContainerName,
};
const connectionContainerProvider = {
provide: getContainerToken(mongoContainerName),
useFactory: () => new Map<any, MongoClient>(),
};
const clientProvider = {
provide: getClientToken(mongoContainerName),
useFactory: async (
connections: Map<any, MongoClient>,
mongoModuleOptions: MongoModuleOptions,
) => {
const { uri, clientOptions } = mongoModuleOptions;
const key = hash.sha1({
uri: uri,
clientOptions: clientOptions,
});
if (connections.has(key)) {
return connections.get(key);
}
const client = new MongoClient(
uri,
clientOptions || DEFAULT_MONGO_CLIENT_OPTIONS,
);
connections.set(key, client);
return await client.connect();
},
inject: [getContainerToken(mongoContainerName), MONGO_MODULE_OPTIONS],
};
const dbProvider = {
provide: getDbToken(mongoContainerName),
useFactory: (
mongoModuleOptions: MongoModuleOptions,
client: MongoClient,
) => client.db(mongoModuleOptions.dbName),
inject: [MONGO_MODULE_OPTIONS, getClientToken(mongoContainerName)],
};
const asyncProviders = this.createAsyncProviders(options);
return {
module: MongoCoreModule,
imports: options.imports,
providers: [
...asyncProviders,
clientProvider,
dbProvider,
containerNameProvider,
connectionContainerProvider,
],
exports: [clientProvider, dbProvider],
};
}
async onModuleDestroy() {
const clientsMap: Map<any, MongoClient> = this.moduleRef.get<
Map<any, MongoClient>
>(getContainerToken(this.containerName));
if (clientsMap) {
await Promise.all(
[...clientsMap.values()].map(connection => connection.close()),
);
}
}
private static createAsyncProviders(
options: MongoModuleAsyncOptions,
): Provider[] {
if (options.useExisting || options.useFactory) {
return [this.createAsyncOptionsProvider(options)];
} else if (options.useClass) {
return [
this.createAsyncOptionsProvider(options),
{
provide: options.useClass,
useClass: options.useClass,
},
];
} else {
return [];
}
}
private static createAsyncOptionsProvider(
options: MongoModuleAsyncOptions,
): Provider {
if (options.useFactory) {
return {
provide: MONGO_MODULE_OPTIONS,
useFactory: options.useFactory,
inject: options.inject || [],
};
} else if (options.useExisting) {
return {
provide: MONGO_MODULE_OPTIONS,
useFactory: async (optionsFactory: MongoOptionsFactory) =>
await optionsFactory.createMongoOptions(),
inject: [options.useExisting],
};
} else if (options.useClass) {
return {
provide: MONGO_MODULE_OPTIONS,
useFactory: async (optionsFactory: MongoOptionsFactory) =>
await optionsFactory.createMongoOptions(),
inject: [options.useClass],
};
} else {
throw new Error('Invalid MongoModule options');
}
}
}
Check out the full implementation

How to unit test Controller and mock #InjectModel in the Service constructor

I am getting issues while unit testing my controller and getting an error "Nest can't resolve dependencies of my service".
For maximum coverage I wanted to unit test controller and respective services and would like to mock external dependencies like mongoose connection. For the same I already tried suggestions mentioned in the below link but didn't find any luck with that:
https://github.com/nestjs/nest/issues/194#issuecomment-342219043
Please find my code below:
export const deviceProviders = [
{
provide: 'devices',
useFactory: (connection: Connection) => connection.model('devices', DeviceSchema),
inject: ['DbConnectionToken'],
},
];
export class DeviceService extends BaseService {
constructor(#InjectModel('devices') private readonly _deviceModel: Model<Device>) {
super();
}
async getDevices(group): Promise<any> {
try {
return await this._deviceModel.find({ Group: group }).exec();
} catch (error) {
return Promise.reject(error);
}
}
}
#Controller()
export class DeviceController {
constructor(private readonly deviceService: DeviceService) {
}
#Get(':group')
async getDevices(#Res() response, #Param('group') group): Promise<any> {
try {
const result = await this.deviceService.getDevices(group);
return response.send(result);
}
catch (err) {
return response.status(422).send(err);
}
}
}
#Module({
imports: [MongooseModule.forFeature([{ name: 'devices', schema: DeviceSchema }])],
controllers: [DeviceController],
components: [DeviceService, ...deviceProviders],
})
export class DeviceModule { }
Unit test:
describe('DeviceController', () => {
let deviceController: DeviceController;
let deviceService: DeviceService;
const response = {
send: (body?: any) => { },
status: (code: number) => response,
};
beforeEach(async () => {
const module = await Test.createTestingModule({
controllers: [DeviceController],
components: [DeviceService, ...deviceProviders],
}).compile();
deviceService = module.get<DeviceService>(DeviceService);
deviceController = module.get<DeviceController>(DeviceController);
});
describe('getDevices()', () => {
it('should return an array of devices', async () => {
const result = [{
Group: 'group_abc',
DeviceId: 'device_abc',
},
{
Group: 'group_xyz',
DeviceId: 'device_xyz',
}];
jest.spyOn(deviceService, 'getDevices').mockImplementation(() => result);
expect(await deviceController.getDevices(response, null)).toBe(result);
});
});
});
When I am running my test case above, I am getting two errors:
Nest can't resolve dependencies of the DeviceService (?). Please make sure that the argument at index [0] is available in the current context.
Cannot spyOn on a primitive value; undefined given
Example code:
import { Test } from '#nestjs/testing';
import { getModelToken } from '#nestjs/mongoose';
describe('auth', () => {
let deviceController: DeviceController;
let deviceService: DeviceService;
const mockRepository = {
find() {
return {};
}
};
beforeAll(async () => {
const module = await Test.createTestingModule({
imports: [DeviceModule]
})
.overrideProvider(getModelToken('Auth'))
.useValue(mockRepository)
.compile();
deviceService = module.get<DeviceService>(DeviceService);
});
// ...
});
You are not injecting the correct token here. Instead of a plain string you have to use the function getModelToken.
import { getModelToken } from '#nestjs/mongoose';
// ...
{ provide: getModelToken('devices'), useFactory: myFactory },
Here is the solution provided by this repo. See the mongo-sample. I am testing my API using the #injectModel and another service. Here's the snippet:
import { CategoriesService } from './../categories/categories.service';
import { getModelToken } from '#nestjs/mongoose';
import { Test, TestingModule } from '#nestjs/testing';
import { ProductsService } from './products.service';
describe('ProductsService', () => {
let service: ProductsService;
beforeAll(async () => {
const module: TestingModule = await Test.createTestingModule({
// getModelToken to mock the MongoDB connection
providers: [
ProductsService,
CategoriesService,
{
provide: getModelToken('Product'),
useValue: {
find: jest.fn(),
findOne: jest.fn(),
findByIdAndUpdate: jest.fn(),
findByIdAndRemove: jest.fn(),
save: jest.fn(),
},
},
{
provide: getModelToken('Category'),
useValue: {
find: jest.fn(),
findOne: jest.fn(),
findByIdAndUpdate: jest.fn(),
findByIdAndRemove: jest.fn(),
save: jest.fn(),
},
},
],
}).compile();
service = module.get<ProductsService>(ProductsService);
});
// your test case
});

Resources