Hi I have a follow code:
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { INote, Note, NoteDocument } from 'src/db/note.schema';
import { NoteAuthorList, NoteDetail } from '../notes-model';
import { INotesQueryService } from './../inotes-query.service';
@Injectable()
export class NotesQueryService implements INotesQueryService {
constructor(@InjectModel(Note.name) private readonly model: Model<NoteDocument>) { }
public async findByAuthorAndLikeText(author: string, query?: string): Promise<NoteAuthorList[]> {
return query ? (await this.model.find({ author })
.find({ $text: { $search: query } })) :
(await this.model.find({ author }))
}
public async findById(id: string): Promise<NoteDetail> {
const document = await this.model.findById(id)
if (!document) {
throw new NotFoundException(`A nota com id ${id} não foi encontrada`)
}
return document
}
}
for this code I wrote a follow tests:
import { getModelToken } from "@nestjs/mongoose";
import { Test, TestingModule } from "@nestjs/testing";
import { Model } from "mongoose";
import { faker } from "@faker-js/faker";
import { INote, Note, NoteDocument } from "../../../../src/db/note.schema";
import { NotesQueryService } from "../../../../src/services/notes/impl/notes-query.service";
import { INotesQueryService } from "../../../../src/services/notes/inotes-query.service"
import { NOTES_SERVICE_TOKENS } from "../../../../src/services/notes/token/notes.token";
import { noteDocumentFactory } from "../../..//bots/services/notes-model.factory";
import { ObjectId } from "mongodb";
import { an } from "@faker-js/faker/dist/airline-D6ksJFwG";
describe('NoteQueryService', () => {
let queryService: INotesQueryService
const noteModelMock = {
findById: jest.fn(),
find: jest.fn()
} as jest.Mocked<Partial<Model<NoteDocument>>>;
const noteModelMock2 = {
find: jest.fn()
} as jest.Mocked<Partial<Model<NoteDocument>>>;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
{ provide: NOTES_SERVICE_TOKENS.QUERY_SERVICE, useClass: NotesQueryService },
{ provide: getModelToken(Note.name), useValue: noteModelMock }
]
})pile();
queryService = module.get<INotesQueryService>(NOTES_SERVICE_TOKENS.QUERY_SERVICE)
})
it('when note is stored and try find it by id then return it', async () => {
const storedNote = noteDocumentFactory.build() as INote
noteModelMock.findById!.mockResolvedValue(storedNote as NoteDocument)
const actual = await queryService.findById(storedNote.id)
expect(actual).toEqual(storedNote)
expect(noteModelMock.findById).toHaveBeenCalledWith(storedNote.id);
})
it('when not isn`t stored and try find it by id then throw error', async () => {
const id = new ObjectId().toHexString()
noteModelMock.findById!.mockResolvedValue(undefined)
await expect(queryService.findById(id)).rejects.toThrow()
expect(noteModelMock.findById).toHaveBeenCalledWith(id);
})
it('when request filter by body then filter it', async () => { // this test I need to fix
const storedNotes = noteDocumentFactory.buildList(5) as INote[]
const query = faker.lorem.word()
const author = faker.lorem.word()
noteModelMock.find!.mockResolvedValue(noteModelMock2)
noteModelMock2.find!.mockResolvedValue(storedNotes)
console.log(noteModelMock.find({ author }))
queryService.findByAuthorAndLikeText(author, query)
expect(noteModelMock.find).toHaveBeenCalledWith({ $text: { $search: query } })
expect(noteModelMock.find).toHaveBeenCalledWith({ author })
expect(noteModelMock.find).toHaveBeenCalledTimes(2)
})
it('when query filter is null, empty or undefined then no call second filter', async () => {
const storedNotes = noteDocumentFactory.buildList(5) as INote[]
const author = faker.lorem.word()
noteModelMock.find!.mockResolvedValue(storedNotes)
await queryService.findByAuthorAndLikeText(author)
expect(noteModelMock.find).toHaveBeenCalledWith({ author })
expect(noteModelMock.find).toHaveBeenCalledTimes(1)
})
})
In a test 'when request filter by body then filter it' I need to mock a chain call by find() method in mongoose model, I try to use this solution for fix:
How do I mock and test chained function with jest?
but this solution a chained call dont't chained a same method, for my case how can I fix my test?
Hi I have a follow code:
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { INote, Note, NoteDocument } from 'src/db/note.schema';
import { NoteAuthorList, NoteDetail } from '../notes-model';
import { INotesQueryService } from './../inotes-query.service';
@Injectable()
export class NotesQueryService implements INotesQueryService {
constructor(@InjectModel(Note.name) private readonly model: Model<NoteDocument>) { }
public async findByAuthorAndLikeText(author: string, query?: string): Promise<NoteAuthorList[]> {
return query ? (await this.model.find({ author })
.find({ $text: { $search: query } })) :
(await this.model.find({ author }))
}
public async findById(id: string): Promise<NoteDetail> {
const document = await this.model.findById(id)
if (!document) {
throw new NotFoundException(`A nota com id ${id} não foi encontrada`)
}
return document
}
}
for this code I wrote a follow tests:
import { getModelToken } from "@nestjs/mongoose";
import { Test, TestingModule } from "@nestjs/testing";
import { Model } from "mongoose";
import { faker } from "@faker-js/faker";
import { INote, Note, NoteDocument } from "../../../../src/db/note.schema";
import { NotesQueryService } from "../../../../src/services/notes/impl/notes-query.service";
import { INotesQueryService } from "../../../../src/services/notes/inotes-query.service"
import { NOTES_SERVICE_TOKENS } from "../../../../src/services/notes/token/notes.token";
import { noteDocumentFactory } from "../../..//bots/services/notes-model.factory";
import { ObjectId } from "mongodb";
import { an } from "@faker-js/faker/dist/airline-D6ksJFwG";
describe('NoteQueryService', () => {
let queryService: INotesQueryService
const noteModelMock = {
findById: jest.fn(),
find: jest.fn()
} as jest.Mocked<Partial<Model<NoteDocument>>>;
const noteModelMock2 = {
find: jest.fn()
} as jest.Mocked<Partial<Model<NoteDocument>>>;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
{ provide: NOTES_SERVICE_TOKENS.QUERY_SERVICE, useClass: NotesQueryService },
{ provide: getModelToken(Note.name), useValue: noteModelMock }
]
})pile();
queryService = module.get<INotesQueryService>(NOTES_SERVICE_TOKENS.QUERY_SERVICE)
})
it('when note is stored and try find it by id then return it', async () => {
const storedNote = noteDocumentFactory.build() as INote
noteModelMock.findById!.mockResolvedValue(storedNote as NoteDocument)
const actual = await queryService.findById(storedNote.id)
expect(actual).toEqual(storedNote)
expect(noteModelMock.findById).toHaveBeenCalledWith(storedNote.id);
})
it('when not isn`t stored and try find it by id then throw error', async () => {
const id = new ObjectId().toHexString()
noteModelMock.findById!.mockResolvedValue(undefined)
await expect(queryService.findById(id)).rejects.toThrow()
expect(noteModelMock.findById).toHaveBeenCalledWith(id);
})
it('when request filter by body then filter it', async () => { // this test I need to fix
const storedNotes = noteDocumentFactory.buildList(5) as INote[]
const query = faker.lorem.word()
const author = faker.lorem.word()
noteModelMock.find!.mockResolvedValue(noteModelMock2)
noteModelMock2.find!.mockResolvedValue(storedNotes)
console.log(noteModelMock.find({ author }))
queryService.findByAuthorAndLikeText(author, query)
expect(noteModelMock.find).toHaveBeenCalledWith({ $text: { $search: query } })
expect(noteModelMock.find).toHaveBeenCalledWith({ author })
expect(noteModelMock.find).toHaveBeenCalledTimes(2)
})
it('when query filter is null, empty or undefined then no call second filter', async () => {
const storedNotes = noteDocumentFactory.buildList(5) as INote[]
const author = faker.lorem.word()
noteModelMock.find!.mockResolvedValue(storedNotes)
await queryService.findByAuthorAndLikeText(author)
expect(noteModelMock.find).toHaveBeenCalledWith({ author })
expect(noteModelMock.find).toHaveBeenCalledTimes(1)
})
})
In a test 'when request filter by body then filter it' I need to mock a chain call by find() method in mongoose model, I try to use this solution for fix:
How do I mock and test chained function with jest?
but this solution a chained call dont't chained a same method, for my case how can I fix my test?
Share Improve this question asked yesterday Jose Luiz JuniorJose Luiz Junior 1952 silver badges13 bronze badges1 Answer
Reset to default 1You have some approaches to do that, but I think with linked returned mocks using mockResolvedValueOnce
and catching these returns with mock.calls
will do the work.
it('when request filter by body then filter it', async () => { // this test I need to fix
const storedNotes = noteDocumentFactory.buildList(5) as INote[]
const query = faker.lorem.word()
const author = faker.lorem.word()
noteModelMock.find!.mockResolvedValueOnce(noteModelMock2).mockResolvedValueOnce(storedNotes)
queryService.findByAuthorAndLikeText(author, query)
expect(noteModelMock.find.mock.calls[1][0]).toHaveBeenCalledWith({ $text: { $search: query } })
expect(noteModelMock..find.mock.calls[0][0]).toHaveBeenCalledWith({ author })
expect(noteModelMock.find).toHaveBeenCalledTimes(2)
})