Laravel 6.2 Docker环境下PHPUnit无法切换至testing环境求助
我仔细看了你的配置和遇到的问题——在Docker容器里跑PHPUnit测试时,明明phpunit.xml和.env.testing都配置了testing环境,结果APP_ENV还是local,还误删了本地数据库,确实挺头疼的。结合你的场景,我整理了几个针对性的排查和修复步骤:
1. 先排查容器内的环境变量优先级
Laravel加载环境的规则是服务器环境变量 > .env文件 > phpunit.xml配置。你先进入容器,跑个命令看看是不是有环境变量把APP_ENV硬设成local了:
echo $APP_ENV
如果输出是local,那就是容器启动时注入了这个变量。你需要修改docker-compose.yml里app服务的environment块,明确加上测试环境的配置:
app: # ...其他原有配置 environment: PHP_IDE_CONFIG: "serverName=localhost" APP_ENV: testing # 新增这行,强制容器内默认用testing环境
改完后重启容器生效:
docker-compose down && docker-compose build && docker-compose up -d
2. 彻底清理配置缓存,避免旧配置干扰
Laravel的配置缓存有时候会顽固保留旧值,尤其是不同环境切换的时候。你在容器里先把缓存清干净再跑测试:
# 清除所有环境的配置缓存 php artisan config:clear php artisan cache:clear # 再直接运行测试 vendor/bin/phpunit
另外也确认下.env.testing是不是真的在容器里——你的docker-compose.yml已经把本地目录挂载到/var/www了,不过还是可以进容器看看:ls -la /var/www/.env.testing,确保文件存在且权限正常。
3. 加个调试测试,确认PHPUnit的配置加载情况
你可以写个简单的测试方法,看看环境变量到底是哪一步出了问题:
public function testCheckEnvironment() { dd( config('app.env'), // Laravel最终用的环境 $_ENV['APP_ENV'], // 系统环境变量 getenv('APP_ENV'), // 系统环境变量另一种获取方式 config('database.default') // 看看数据库连接是不是走的测试库 ); }
运行这个测试,如果config('app.env')是local,但$_ENV['APP_ENV']是testing,说明缓存没清干净;如果三个值都是local,那就是容器的环境变量优先级更高。
4. 检查entrypoint.sh启动脚本
你的Dockerfile用了entrypoint.sh作为启动脚本,这个脚本很可能在容器启动时做了配置缓存或者环境变量设置。你打开这个脚本看看:
- 有没有硬写
export APP_ENV=local之类的命令? - 有没有运行
php artisan config:cache但没指定--env=testing?
如果有这些操作,要么修改脚本让它根据环境变量动态处理,要么在测试场景下跳过这些步骤。
5. 临时指定环境变量跑测试(VSCode适配方案)
其他团队用PHPStorm没问题,大概率是因为PHPStorm在跑测试时会单独注入环境变量,而你直接在容器里跑vendor/bin/phpunit时用的是容器默认环境。你可以试试在跑PHPUnit时临时指定环境:
APP_ENV=testing vendor/bin/phpunit
如果这样能正常进入testing环境,说明容器默认环境是local,你可以把这个命令做成别名或者写个小脚本,方便日常用。
额外提醒:数据库连接的坑
你phpunit.xml里写了DB_CONNECTION=workit_testing,记得在config/database.php里把这个连接的主机设成testdb(Docker服务名),而不是127.0.0.1——因为在容器内部,服务名可以直接当主机名用,这样测试时才会连到testdb容器的数据库,而不是本地的3306端口:
'workit_testing' => [ 'driver' => 'mysql', 'host' => env('DB_HOST', 'testdb'), 'port' => env('DB_PORT', '3306'), 'database' => env('DB_DATABASE', 'workit_test'), 'username' => env('DB_USERNAME', 'local'), 'password' => env('DB_PASSWORD', 'local'), // ...其他配置 ],
测试前记得备份本地数据库,避免再被误删~
内容的提问来源于stack exchange,提问作者Matt Larsuma

