skip to Main Content

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


  1. 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 the HttpService and remove the imports property and array from your test setup.

    {
      provide: HttpService,
      useValue: {
        get: () => of({ data: shibeArray })
      }
    }
    

    And that should be enough to get your test passing.

    Login or Signup to reply.
  2. edit your Shibe.Module.ts imports into this:
    imports: [MongooseModule.forFeature([{ name: Shibe.name, schema: ShibeSchema }]), HttpModule, ShibeModel]

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search