NestJS单元测试Mock Sequelize模型时findAll报错的解决求助
NestJS单元测试Mock Sequelize模型的问题解决方案
问题场景
使用NestJS构建CRUD API时,编写服务单元测试时Mock Sequelize模型出现报错,测试代码及错误信息如下:
测试代码
import { getModelToken } from "@nestjs/sequelize"; import { Test, TestingModule } from "@nestjs/testing"; import { VacanciesService } from "../../vacancies.service"; import { DepartmentsServices } from "../../../departments/departments.service"; import { Departments } from "../../../departments/model/departments.model"; import { Vacancies } from "../../model/vacancies.model"; describe("Vacancies service", () => { let service: VacanciesService; const mockSequelizeDepartments = { findByPk: jest.fn(), }; const mockSequelizeVacancies = { findAll: jest.fn(), }; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ VacanciesService, { provide: getModelToken(Vacancies), useValue: { mockSequelizeVacancies } }, DepartmentsServices, { provide: getModelToken(Departments), useValue: { mockSequelizeDepartments } }, ], }).compile(); service = module.get<VacanciesService>(VacanciesService); }); it("should be defined", () => { expect(service).toBeDefined(); }); describe("List vacancies", () => { it("should list all vacancies and return an empty array", async () => { const list = await service.list(); expect(list).toHaveLength(0); expect(mockSequelizeVacancies.findAll).toHaveBeenCalledTimes(1); }); }); });
报错信息
TypeError: this.vacanciesModel.findAll is not a function 57 | 58 | async list() { > 59 | const list = await this.vacanciesModel.findAll(); | ^ 60 | 61 | if (!list) throw new NotFoundException("Nenhuma vaga encontrada"); 62 |
尝试修改findAll为findAll() { "Do something" }或findAll: () => { "Do something" }后仍报错。
问题原因
Mock模型的注入方式错误:你把mockSequelizeVacancies和mockSequelizeDepartments额外嵌套了一层对象,导致注入后的模型结构变为{ mockSequelizeVacancies: { findAll: jest.fn() } },服务中调用this.vacanciesModel.findAll()自然找不到对应方法。
同时,原Mock的findAll未设置返回值,即使解决注入问题,调用service.list()也会因为返回undefined触发NotFoundException。
解决步骤
- 修正Mock注入方式:直接将
mockSequelizeVacancies和mockSequelizeDepartments作为useValue的值,移除额外的对象包裹。 - 设置Mock方法返回值:给
findAll添加mockResolvedValue([]),确保返回空数组,避免触发服务中的异常。
修改后的测试代码
import { getModelToken } from "@nestjs/sequelize"; import { Test, TestingModule } from "@nestjs/testing"; import { NotFoundException } from "@nestjs/common"; import { VacanciesService } from "../../vacancies.service"; import { DepartmentsServices } from "../../../departments/departments.service"; import { Departments } from "../../../departments/model/departments.model"; import { Vacancies } from "../../model/vacancies.model"; describe("Vacancies service", () => { let service: VacanciesService; const mockSequelizeDepartments = { findByPk: jest.fn(), }; const mockSequelizeVacancies = { findAll: jest.fn().mockResolvedValue([]), // 设置返回空数组 }; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ VacanciesService, { provide: getModelToken(Vacancies), useValue: mockSequelizeVacancies }, // 直接传入Mock对象 DepartmentsServices, { provide: getModelToken(Departments), useValue: mockSequelizeDepartments }, // 同理修正 ], }).compile(); service = module.get<VacanciesService>(VacanciesService); }); it("should be defined", () => { expect(service).toBeDefined(); }); describe("List vacancies", () => { it("should list all vacancies and return an empty array", async () => { const list = await service.list(); expect(list).toHaveLength(0); expect(mockSequelizeVacancies.findAll).toHaveBeenCalledTimes(1); }); // 可选:测试无数据时的异常抛出逻辑 it("should throw NotFoundException when no vacancies found", async () => { mockSequelizeVacancies.findAll.mockResolvedValue(null); await expect(service.list()).rejects.toThrow(NotFoundException); }); }); });
关键说明
- 移除
useValue中的对象嵌套是核心修复点,确保注入的Mock模型直接包含所需的方法。 - 设置
mockResolvedValue可以模拟Sequelize异步查询的返回结果,让测试逻辑正常执行。
内容的提问来源于stack exchange,提问作者izakVoigt
相关产品推荐
相关产品推荐

