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

使用pg-mem测试时遇RelationNotFound:pg_enum不存在的解决求助

问题

在Jest测试TypeScript项目仓库层时,使用pg-mem创建内存PostgreSQL数据库,ORM采用sequelize-typescript。部分模型包含枚举类型,执行sequelize.sync({ force: true })时报错:RelationNotFound [Error]: relation "pg_enum" does not exist——原因是sequelize会查询PostgreSQL的pg_enum系统目录处理枚举,但pg-mem默认未实现该系统表。

失败的查询语句:

select
    t.typname enum_name,
    array_agg(e.enumlabel order by enumsortorder) enum_value
from
    pg_type t
join pg_enum e on
    t.oid = e.enumtypid
join pg_catalog.pg_namespace n on
    n.oid = t.typnamespace
where
    n.nspname = 'public'
    and t.typname = 'enum_assets_status'
group by
    1;

注:测试用例复用了sequelize-typescript创建的现有模型声明。

当前配置代码:

import { DataType, newDb } from "pg-mem";
import { Sequelize } from "sequelize-typescript";

import { modelA, modelB } from "../../database/models";

describe("test", () => {
    const db = newDb();

    const sequelize = new Sequelize({
        dialect: "postgres",
        dialectModule: db.adapters.createPg(),
        models: [
          modelA,
          modelB
        ]
    });

    sequelize.sync({ force: true });

    //////////// Test Cases //////////////
    //////////////////////////////////////
    //////////////////////////////////////
});

已尝试的无效方法:
手动创建pg_enum表但未生效:

db.registerLanguage("plpgsql", ({ code, args, returns }) => {
        return () => {
            db.public.none(`CREATE TABLE pg_enum (
                oid OID,
                enumtypid OID,
                enumsortorder NUMBER,
                enumlabel TEXT
            )`);
            db.public.none(`INSERT INTO pg_enum ("oid",enumtypid,enumsortorder,enumlabel) VALUES
                (29188,29184,2.0,'INCOMPLETE');`);
        };
    });
解决方法

方案1:模拟pg_catalog下的pg_enum系统表

pg_enum属于pg_catalog命名空间而非public,需在对应命名空间下创建表并插入枚举数据,同时补充pg_type的对应记录:

describe("test", () => {
    const db = newDb();

    // 在pg_catalog下创建pg_enum表
    db.pgCatalog.none(`CREATE TABLE pg_enum (
        enumtypid OID,
        enumsortorder FLOAT,
        enumlabel TEXT
    )`);

    // 为目标枚举类型插入数据(示例为enum_assets_status)
    const enumOid = 10001; // 可指定任意有效OID
    db.pgCatalog.none(`INSERT INTO pg_enum (enumtypid, enumsortorder, enumlabel) VALUES
        ($1, 1.0, 'INCOMPLETE'),
        ($1, 2.0, 'COMPLETE'),
        ($1, 3.0, 'ARCHIVED')`, [enumOid]);

    // 向pg_type插入枚举类型的元数据
    db.pgCatalog.none(`INSERT INTO pg_type (oid, typname, typnamespace, typtype) VALUES
        ($1, 'enum_assets_status', (SELECT oid FROM pg_namespace WHERE nspname='public'), 'e')`, [enumOid]);

    const sequelize = new Sequelize({
        dialect: "postgres",
        dialectModule: db.adapters.createPg(),
        models: [modelA, modelB]
    });

    await sequelize.sync({ force: true });

    // 测试用例...
});

方案2:拦截pg_enum查询并返回模拟结果

通过pg-mem的查询拦截功能,直接返回sequelize期望的枚举数据:

describe("test", () => {
    const db = newDb();

    // 拦截pg_enum相关查询
    db.public.interceptQueries((query) => {
        if (query.text.includes('pg_enum') && query.text.includes('enum_assets_status')) {
            return {
                rows: [{
                    enum_name: 'enum_assets_status',
                    enum_value: ['INCOMPLETE', 'COMPLETE', 'ARCHIVED']
                }]
            };
        }
        return null; // 其他查询正常处理
    });

    const sequelize = new Sequelize({
        dialect: "postgres",
        dialectModule: db.adapters.createPg(),
        models: [modelA, modelB]
    });

    await sequelize.sync({ force: true });

    // 测试用例...
});

方案3:临时替换枚举为字符串类型

若测试无需严格验证枚举逻辑,可在测试中覆盖模型的枚举字段类型:

describe("test", () => {
    const db = newDb();

    const sequelize = new Sequelize({
        dialect: "postgres",
        dialectModule: db.adapters.createPg()
    });

    // 覆盖模型中的枚举字段为STRING类型
    modelA.init(
        {
            // 保留其他原有字段
            status: {
                type: DataType.STRING,
                allowNull: false
            }
        },
        { sequelize, modelName: 'modelA' }
    );

    // 同理处理modelB的枚举字段
    modelB.init(/* 覆盖枚举字段 */, { sequelize, modelName: 'modelB' });

    await sequelize.sync({ force: true });

    // 测试用例...
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 04:40:36