I have looked the examples on Mongo testing from here:
The example tests and has mock implementations of the methods from the service but I have not got that far. I have provided the getModelToken but that does not seem to do the trick in my case.
this is the error message I receive and below are the snippets of my code:
ShibeService › should be defined
Nest can't resolve dependencies of the ShibeModel (?). Please make sure that the argument DatabaseConnection at index [0] is available in the MongooseModule context.
Potential solutions:
- If DatabaseConnection is a provider, is it part of the current MongooseModule?
- If DatabaseConnection is exported from a separate @Module, is that module imported within MongooseModule?
@Module({
imports: [ /* the Module containing DatabaseConnection */ ]
})
ShibeService.Spec.Ts
import { HttpModule } from '@nestjs/axios';
import { Test, TestingModule } from '@nestjs/testing';
import { ShibeService } from './shibe.service';
import { ShibeModule } from './shibe.module';
import { getModelToken } from '@nestjs/mongoose';
import { Shibe } from './schemas/shibe.schema';
describe('ShibeService', () => {
let service: ShibeService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
ShibeService,
{
provide: getModelToken(Shibe.name),
useValue: jest.fn(),
},
],
imports: [HttpModule, ShibeModule],
}).compile();
service = module.get<ShibeService>(ShibeService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});
shibe.service.ts
import { Injectable, OnModuleInit } from '@nestjs/common';
import { Model } from 'mongoose';
import { CreateShibe } from './models/create-shibe.model';
import { uniqueNamesGenerator, Config, names } from 'unique-names-generator';
import { Shibe, ShibeDocument } from './schemas/shibe.schema';
import { InjectModel } from '@nestjs/mongoose';
import { HttpService } from '@nestjs/axios';
import { map } from 'rxjs';
import {v4 as uuidv4} from 'uuid';
@Injectable()
export class ShibeService implements OnModuleInit {
apiUrl: string;
shibes: Shibe[];
constructor(
private httpService: HttpService,
@InjectModel(Shibe.name) private readonly shibeModel: Model<ShibeDocument>,
) {
this.apiUrl = 'http://shibe.online/api/shibes';
}
async onModuleInit() {
// when model is initalised
//check if database has shibes, if not populate it with 100 shibes
const shibesInDatabase = await this.shibeModel.count({});
const config: Config = {
dictionaries: [names],
};
if (shibesInDatabase < 20) {
this.httpService
.get<string[]>(`${this.apiUrl}?count=10`)
.pipe(map((response) => response.data))
.subscribe((urls: string[]) => {
const shibes = urls.map((url: string) => {
return {
name: uniqueNamesGenerator(config),
url,
};
});
console.log(...shibes);
this.shibeModel.create(...shibes)
});
}
}
async create(createShibeDto: CreateShibe): Promise<Shibe> {
const createdShibe = await this.shibeModel.create(createShibeDto);
return createdShibe;
}
async findAll(): Promise<Shibe[]> {
return this.shibeModel.find({}).exec();
}
async findOne(id: string): Promise<Shibe> {
return this.shibeModel.findOne({ _id: id }).exec();
}
async delete(id: string) {
const deletedShibe = await this.shibeModel
.findByIdAndRemove({ _id: id })
.exec();
return deletedShibe;
}
}
shibe.module.ts
import { Module } from '@nestjs/common';
import { ShibeService } from './shibe.service';
import { ShibeController } from './shibe.controller';
import { MongooseModule } from '@nestjs/mongoose';
import { Shibe, ShibeSchema } from './schemas/shibe.schema';
import { HttpModule } from '@nestjs/axios';
@Module({
controllers: [ShibeController],
providers: [ShibeService],
imports: [MongooseModule.forFeature([{ name: Shibe.name, schema: ShibeSchema }]), HttpModule],
})
export class ShibeModule {}
shibe.schema
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { ApiProperty } from '@nestjs/swagger';
import { Document } from 'mongoose';
export type ShibeDocument = Shibe & Document;
@Schema()
export class Shibe {
@ApiProperty({ example: 'Dodge', description: 'The shibe dog name' })
@Prop({ required: true })
name: string;
@Prop({ required: true })
@ApiProperty({ example: 'http://image.jpg', description: 'The shibe image url' })
url: string;
@ApiProperty({ example: '12343', description: 'The shibe id' })
@Prop()
id: string;
}
export const ShibeSchema = SchemaFactory.createForClass(Shibe);
I am only testing that the service works
2
Answers
If you’re just doing unit testing, I would highly advise against adding any
imports
. Any providers that the class you’re testing needs can be mocked with a custom provider as shown in this repo. In fact, you already mock out the@InjectModel(Shibe.name)
so the only thing left to do would be to write a custom provider for theHttpService
and remove theimports
property and array from your test setup.And that should be enough to get your test passing.
edit your Shibe.Module.ts imports into this:
imports: [MongooseModule.forFeature([{ name: Shibe.name, schema: ShibeSchema }]), HttpModule, ShibeModel]