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

执行NestJS E2E测试时Prisma报P1017连接关闭错误

问题:执行NestJS E2E测试脚本时出现P1017数据库连接错误

我正在学习NestJS相关课程,为测试环境配置了.env.test文件,仅与开发环境的.env在数据库端口上有差异:

.env配置

PORT=3002
JWT_SECRET=secret
DB_USERNAME=root
DB_PASSWORD=MySQL.Bebon3232
DB_HOST=db_test
DB_NAME=learning_nestjs
DATABASE_URL="mysql://root:MySQL.Bebon3232@localhost:3307/learning_nestjs"

.env.test配置

PORT=3002
JWT_SECRET=secret
DB_USERNAME=root
DB_PASSWORD=MySQL.Bebon3232
DB_HOST=db_test
DB_NAME=learning_nestjs
DATABASE_URL="mysql://root:MySQL.Bebon3232@localhost:3308/learning_nestjs"

Docker Compose配置了两个MySQL容器:dev_db(映射3307端口)和test_db(映射3308端口),开发环境运行正常,但执行test:e2e脚本时出现问题。

package.json脚本配置

"prisma:dev:deploy": "prisma migrate deploy",
"db:dev:up": "docker compose up dev_db -d",
"db:dev:rm": "docker compose rm dev_db -s -f -v",
"db:dev:restart": "yarn db:dev:rm && yarn db:dev:up && yarn prisma:dev:deploy",

"prisma:test:deploy": "dotenv -e .env.test -- prisma migrate deploy",
"db:test:up": "docker compose up test_db -d",
"db:test:rm": "docker compose rm test_db -s -f -v",
"db:test:restart": "yarn db:test:rm && yarn db:test:up && yarn prisma:test:deploy",

"build": "nest build",
"start": "nest start",
"start:dev": "nest start --watch",

"pretest:e2e": "yarn db:test:restart",
"test:e2e": "dotenv -e .env.test -- jest --watchAll --no-cache --config ./test/jest-e2e.json"

执行test:e2e时会依次运行:

  1. yarn compose rm test_db -s -f -v
  2. yarn compose up test_db -d
  3. dotenv -e .env.test -- prisma migrate deploy

第三步执行时出现错误:

Error: P1017: Server has closed the connection.
error Command failed with exit code 1.

但单独执行以下命令均正常:

npx dotenv -e .env.test -- prisma migrate deploy
npx dotenv -e .env.test -- jest --watchAll --no-cache --config ./test/jest-e2e.json

E2E测试代码

import { INestApplication, ValidationPipe } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import { AppModule } from '../src/app.module';

describe('app e2e', () => {
  let app: INestApplication;

  beforeAll(async () => {
    const moduleRef = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = moduleRef.createNestApplication();
    app.useGlobalPipes(
      new ValidationPipe({
        whitelist: true,
      }),
    );
    await app.init();
  });

  afterAll(async () => {
    await app.close();
  });

  it.todo('should pass');
});

注:dev_db和test_db容器均可正常运行,请问该如何解决批量执行命令时出现的P1017错误?


解决方案

核心问题是MySQL容器启动后需要时间完成初始化(如创建数据库、加载系统表等),脚本直接执行migrate会因数据库未就绪导致连接失败,可以通过以下几种方式解决:

方式1:使用等待工具检测数据库就绪

安装wait-for-it工具,它会等待指定端口的服务就绪后再执行后续命令:

npm install wait-for-it --save-dev

修改db:test:restart脚本:

"db:test:restart": "yarn db:test:rm && yarn db:test:up && wait-for-it localhost:3308 -t 60 -- yarn prisma:test:deploy"

-t 60表示最多等待60秒,超时则终止。

方式2:添加命令重试机制

安装retry-cli工具,让migrate命令在失败时自动重试:

npm install retry-cli --save-dev

修改prisma:test:deploy脚本:

"prisma:test:deploy": "dotenv -e .env.test -- retry -n 5 -d 3 prisma migrate deploy"

-n 5表示最多重试5次,-d 3表示每次重试间隔3秒。

方式3:给Docker容器添加健康检查

在Docker Compose的test_db配置中加入健康检查,确保容器真正就绪后才允许后续命令执行:

services:
  test_db:
    image: mysql:8.0
    ports:
      - "3308:3306"
    environment:
      MYSQL_ROOT_PASSWORD: MySQL.Bebon3232
      MYSQL_DATABASE: learning_nestjs
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-pMySQL.Bebon3232"]
      timeout: 20s
      retries: 10
      interval: 2s

然后修改db:test:up命令,等待健康检查通过:

"db:test:up": "docker compose up test_db -d && docker compose wait test_db"

方式4:手动添加延迟(简单但不推荐)

直接在脚本中加入sleep命令,给数据库足够的初始化时间:

"db:test:restart": "yarn db:test:rm && yarn db:test:up && sleep 10 && yarn prisma:test:deploy"

这种方式不够灵活,不同环境下所需时间可能不同,容易出现等待过短或过长的问题。


内容的提问来源于stack exchange,提问作者El-Baraa Radwan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 16:23:12