执行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时会依次运行:
yarn compose rm test_db -s -f -vyarn compose up test_db -ddotenv -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
相关产品推荐
相关产品推荐

