You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用pg-mem的clone函数解决测试时schema变更引发的备份恢复报错

解决方案

backup.restore()仅支持备份后schema未发生修改的场景,只要测试中出现创建/删除表、修改字段结构等schema变更操作,就会触发对应报错,官方推荐使用clone()方法处理这类场景。

clone()方法用法

clone()是pg-mem核心实例(即newDb()返回的对象)的原生方法,作用是深拷贝当前实例的完整状态(包含所有schema定义、预置数据),拷贝生成的新实例完全独立,和原实例互不影响,性能远高于每次调用newDb()重新初始化。

最终实现代码

import { newDb } from 'pg-mem';
import {createTables} from './database';

// 初始化基础模板实例,仅执行一次
let baseDbTemplate;
let templateInitialized = false;

export const getTestDatabase = async () => {
  // 首次调用初始化基础模板,完成表创建等公共初始化逻辑
  if (!templateInitialized) {
    templateInitialized = true;
    baseDbTemplate = newDb();
    // 先在模板实例上完成schema初始化
    const templateDb = await baseDbTemplate.adapters.createPgPromise();
    templateDb.connect();
    await createTables(templateDb);
    // 初始化完成后关闭模板的适配器连接,避免占用
    templateDb.$pool.end();
  }
  // 每次测试克隆独立实例,完全隔离
  const testDbInstance = baseDbTemplate.clone();
  // 基于克隆实例生成pg-promise适配器
  const database = await testDbInstance.adapters.createPgPromise();
  database.connect();
  return database;
};

方案优势

  • 彻底避免重复数据库连接警告:仅初始化一次基础模板,后续所有测试用的都是克隆实例生成的独立适配器,不会触发pg-promise的重复对象校验
  • 支持任意schema修改场景:每个测试的数据库实例完全独立,修改schema不会影响其他测试,也不会触发备份还原的schema校验错误
  • 性能更优:仅执行一次公共初始化逻辑,克隆操作的开销远低于每次重新建表初始化

补充:如果确认无需保留测试间的schema变更,也可以在每次测试结束后主动回滚所有DDL操作,但上述clone方案适配性更强,维护成本更低。

内容的提问来源于stack exchange,提问作者mtmacdonald

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 01:54:04