Node.js单元测试Mock SQL连接遇报错:connect不可在指定状态调用求解决
解决建议
核心思路:Mock 掉 tedious 的连接逻辑
不要让测试代码真正初始化 tedious 连接,而是通过 Mock 工具(比如 Jest、Sinon)模拟连接对象及其方法,彻底避免触发真实的数据库登录流程。
1. 用 Jest Mock tedious 核心模块
如果使用 Jest 做测试,直接 Mock 整个 tedious 库,模拟Connection类和关键方法:
// 在测试文件顶部Mock tedious jest.mock('tedious', () => { const mockConnect = jest.fn((callback) => { // 模拟连接成功,直接调用回调且无错误 callback(null); }); const mockClose = jest.fn(); return { Connection: jest.fn(() => ({ connect: mockConnect, close: mockClose, // 按需模拟业务代码用到的其他方法,比如execSql、on等 })), // 模拟业务需要的常量,比如TYPES TYPES: { VarChar: 'VarChar', Int: 'Int' } }; });
测试时业务代码调用new Connection()会得到 Mock 对象,connect方法不会触发真实数据库登录流程,自然不会出现状态冲突报错。
2. 排查业务代码的连接复用逻辑
如果业务代码里存在同一连接实例重复调用connect的情况,即使 Mock 也可能触发状态问题。要确保:
- 每个数据库操作要么使用全新的连接实例,要么在确认连接处于
connected状态后再执行操作 - 避免在未断开连接的实例上再次调用
connect
3. 模拟连接状态(适配复杂测试场景)
如果需要模拟不同连接状态的分支逻辑,可以在 Mock 中添加状态管理:
jest.mock('tedious', () => { let connectionState = 'disconnected'; const mockConnect = jest.fn((callback) => { connectionState = 'connected'; callback(null); }); return { Connection: jest.fn(() => ({ connect: mockConnect, get state() { return connectionState; }, // 其他需要的方法 })) }; });
这样可以模拟连接从断开到成功的状态变化,贴近真实逻辑的同时避免真实连接的状态错误。
4. 清理 Mock 实例(避免跨测试污染)
在每个测试用例前后清理 Mock 的调用记录和状态:
beforeEach(() => { jest.clearAllMocks(); // 若有自定义状态变量,重置为初始值 });
内容的提问来源于stack exchange,提问作者Mu Muthukumar
相关产品推荐
相关产品推荐

