无法Mock TypeORM DataSource,求Jest中更优Mock方案
在Jest中Mock TypeORM DataSource的正确方式
错误原因分析
你遇到的TypeError: Cannot set property DataSource of [object Object] which has only a getter,是因为typeorm.DataSource是TypeORM导出的只读类,只能通过Jest的jest.mock机制来Mock,无法直接赋值覆盖。加上你的AppService是直接导入了预实例化的connectDB对象,所以Mock的核心要针对这个导出的实例,而非DataSource类本身。
优化方案一:直接Mock数据库配置模块
针对你当前的代码结构,最直接的方式是Mock../config/db_connection模块的导出,让它返回一个模拟的DataSource实例:
import { AppService } from '../services'; import connectDB from '../config/db_connection'; // Mock整个db_connection模块 jest.mock('../config/db_connection', () => ({ __esModule: true, default: { manager: { find: jest.fn().mockResolvedValue([]), // 可预设测试用返回值 }, }, })); describe("Tests for AppService", () => { it("should call getServices and trigger manager.find", async () => { const appService = new AppService(); await appService.getServices(1); // 断言find方法被调用 expect(connectDB.manager.find).toHaveBeenCalled(); // 可选:断言调用参数是否符合预期 expect(connectDB.manager.find).toHaveBeenCalledWith( expect.any(Function), { relations: { service: true } } ); }); });
优化方案二:结合NestJS依赖注入(推荐)
如果你的项目基于NestJS,更优雅的方式是通过依赖注入注入DataSource,而非直接导入实例,这样Mock会更灵活:
修改AppService代码
import { Injectable } from '@nestjs/common'; import { DataSource, Like } from 'typeorm'; import { services } from '../entity/services'; import { versions } from '../entity/versions'; @Injectable() export class AppService { // 通过构造函数注入DataSource constructor(private readonly dataSource: DataSource) {} public getServices(id: number): Promise<versions[]> { return this.dataSource.manager.find(versions, { relations: { service: true, }, }); } }
测试文件代码
import { Test } from '@nestjs/testing'; import { AppService } from '../services'; import { DataSource } from 'typeorm'; describe("Tests for AppService", () => { let appService: AppService; let mockDataSource: Partial<DataSource>; beforeEach(async () => { // 构建模拟的DataSource实例 mockDataSource = { manager: { find: jest.fn().mockResolvedValue([]), }, }; // 创建测试模块,注入Mock的DataSource const moduleRef = await Test.createTestingModule({ providers: [ AppService, { provide: DataSource, useValue: mockDataSource, }, ], }).compile(); appService = moduleRef.get<AppService>(AppService); }); it("should call getServices and trigger manager.find", async () => { await appService.getServices(1); expect(mockDataSource.manager.find).toHaveBeenCalled(); }); });
关键注意点
- 不要直接修改TypeORM导出的只读类(比如
typeorm.DataSource),必须用jest.mock或依赖注入的方式Mock依赖。 - 如果是NestJS项目,优先使用依赖注入,这会让测试更符合框架设计,也更容易维护。
内容的提问来源于stack exchange,提问作者Mangesh Tak
相关产品推荐
相关产品推荐

