10

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

3 Answers 3

15

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); }); // ... }); 
Sign up to request clarification or add additional context in comments.

Comments

4

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

Comments

2

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 }); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.