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

测试环境中Sequelize未使用指定测试数据库端口问题排查

问题:Sequelize测试环境连接错误数据库端口

使用Sequelize作为ORM、Jest做测试,通过Docker Compose运行开发库(5432端口)和测试库(5433端口)两个PostgreSQL实例。控制台显示环境变量配置值正确,但测试时Sequelize始终使用默认的5432端口,导致连接到开发库而非测试库。

相关配置文件

docker-compose.yml

version: "3.8"

services:
  db:
    image: postgres
    environment:
      POSTGRES_USER: bana_software
      POSTGRES_PASSWORD: BANASOFTWARE
      POSTGRES_DB: banasoftware
    ports:
      - "5432:5432"
    volumes:
      - db_data_dev:/var/lib/postgresql/data

  db_test:
    image: postgres
    environment:
      POSTGRES_USER: bana_software
      POSTGRES_PASSWORD: BANASOFTWARE
      POSTGRES_DB: banasoftware_test
    ports:
      - "5433:5432"
    volumes:
      - db_data_test:/var/lib/postgresql/data
volumes:
  db_data_dev:
  db_data_test:

vehicle.test.js

import database from "../config/database";
import request from "supertest";
import app from "../app/app.js";
import { v4 as uuidv4 } from "uuid";
import config from "../helpers/enviroment.js";


describe("Vehicle", () => {
  beforeAll(async () => {
    console.log(database.db.config,config)
    await database.db.sync({ force: true });
    await Vehicle.create({ vehicle_id: uuidv4(), available: true });
  });

  afterAll(async () => {
    const queryInterface = database.db.getQueryInterface();
    const tables = ["Vehicle"]; // 需要清理的表列表

    for (const table of tables) {
      await queryInterface.bulkDelete(table, null, {
        truncate: true,
        cascade: true,
        restartIdentity: true,
      });
    }
    await database.db.close();
  });

  describe("GET /vehicles", () => {
    it("应返回所有车辆", async () => {
      const res = await request(app).get("/api/vehicles");
      expect(res.status).toBe(200);
      expect(res.body).toBeInstanceOf(Array);
      expect(res.body.length).toBe(1);
    });
  });
});

控制台输出

console.log(database.db.config)

{
      database: 'banasoftware_test',
      username: 'bana_software',
      password: 'BANASOFTWARE',
      host: 'localhost',
      port: 5432,
      pool: {},
      protocol: 'tcp',
      native: false,
      ssl: undefined,
      replication: false,
      dialectModule: null,
      dialectModulePath: null,
      keepDefaultTimezone: undefined,
      dialectOptions: undefined
    }

console.log(config)

{
      username: 'bana_software',
      password: 'BANASOFTWARE',
      database: 'banasoftware_test',
      host: 'localhost',
      port: '5343',
      dialect: 'postgres'
    }

.env文件

DB_USER=bana_software
DB_PASSWORD=BANASOFTWARE
DB_NAME=banasoftware_test
DB_HOST=localhost
DB_PORT=5343
PORT=3000
NODE_ENV=test

config/database.js

import { Sequelize } from "sequelize";
import config from "../helpers/enviroment.js";

class Database {
  constructor() {
    this.db = new Sequelize(config.database, config.username, config.password, {
      host: config.host,
      dialect: config.dialect,
    });
  }
}

export default new Database();

app/app.js

import express from "express";
import cors from "cors";
import { VehicleRouter } from "../routers/vehicle.router.js";

class App {
  constructor() {
    this.app = express();
    this.middlewares();
    this.routers();
  }

  middlewares() {
    this.app.use(express.json());
    this.app.use(express.urlencoded({ extended: true }));
    this.app.use(cors());
  }

  routers() {
    const routers = [new VehicleRouter()];
    routers.forEach((router) => {
      this.app.use("/api", router.router);
    });
  }
}

export default new App().app;

.sequelizerc

import path from "path";
// 导出包含数据库相关文件路径的对象
export default {
  // 包含数据库种子文件(数据填充脚本)的目录
  "seeders-path": path.resolve("src/database", "seeders"),
  // 包含数据库迁移文件(schema变更脚本)的目录路径
  "migrations-path": path.resolve("src/database", "migrations"),
  // 数据库配置文件路径
  config: path.resolve("src/database", "config.js"),
};

src/database/config.js

import dotenv from "dotenv";
dotenv.config({ path: `.env.${process.env.NODE_ENV}` });

module.exports = {
  production: {},
  development: {
    dialect: "postgres",
    host: process.env.DB_HOST,
    port: +process.env.DB_PORT,
    username: process.env.DB_USER,
    password: process.env.DB_PASSWORD,
    database: process.env.DB_NAME,
  },
  test: {
    dialect: "postgres",
    host: process.env.DB_HOST,
    port: +process.env.DB_PORT,
    username: process.env.DB_USER,
    password: process.env.DB_PASSWORD,
    database: process.env.DB_NAME,
  },
};

package.json scripts

"scripts": {
    "dev": "cross-env NODE_ENV=development node src/index.js",
    "test": "cross-env NODE_ENV=test jest --verbose --runInBand"
  },

helpers/enviroment.js

import dotenv from "dotenv";

dotenv.config({ path: `.env.${process.env.NODE_ENV}` });

const config = {
  username: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME,
  host: process.env.DB_HOST,
  port: process.env.DB_PORT,
  dialect: "postgres",
};

export default config;

问题分析与修复方案

核心问题1:Sequelize未配置端口参数

在config/database.js中,创建Sequelize实例时未传入port配置项,导致Sequelize使用PostgreSQL默认端口5432,忽略了环境变量中的端口值。

修复:
修改config/database.js,在Sequelize配置对象中添加port参数:

class Database {
  constructor() {
    this.db = new Sequelize(config.database, config.username, config.password, {
      host: config.host,
      dialect: config.dialect,
      port: config.port, // 新增此行,传入环境变量中的端口
    });
  }
}

核心问题2:环境变量端口与Docker映射不匹配

.env文件中DB_PORT设置为5343,但Docker Compose中测试库的映射端口是5433:5432,两者不匹配。

修复:
修改.env文件中的DB_PORT为5433:

DB_PORT=5433

额外优化:将端口转为数字类型

环境变量读取的端口是字符串类型,Sequelize建议传入数字类型,修改helpers/enviroment.js中的port字段:

port: +process.env.DB_PORT,

完成以上修改后,测试环境的Sequelize会正确连接到Docker中映射5433端口的测试数据库。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 05:02:03