最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

node.js - Jest mock chained calls - Stack Overflow

programmeradmin6浏览0评论

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 badges
Add a comment  | 

1 Answer 1

Reset to default 1

You 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)
})
发布评论

评论列表(0)

  1. 暂无评论