为啥 phpunit 没有得到 phpunit.xml 中指定的正确 APP_ENV?
Posted
技术标签:
【中文标题】为啥 phpunit 没有得到 phpunit.xml 中指定的正确 APP_ENV?【英文标题】:Why phpunit is not getting the correct APP_ENV as specified in phpunit.xml?为什么 phpunit 没有得到 phpunit.xml 中指定的正确 APP_ENV? 【发布时间】:2018-02-05 22:07:14 【问题描述】:我正在使用 Laravel,这是我的 ./phpunit.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="bootstrap/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
<testsuites>
<testsuite name="FeatureTests">
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
<testsuite name="UnitTests">
<directory suffix="Test.php">./tests/Unit</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./app</directory>
</whitelist>
</filter>
<php>
<env name="APP_ENV" value="testing"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="QUEUE_DRIVER" value="sync"/>
<env name="DB_CONNECTION" value="sqlite_testing" />
</php>
</phpunit>
我正在使用以下命令触发我的一个测试套件:
./vendor/phpunit/phpunit/phpunit --testsuite UnitTests
在我的测试方法中,我有:
public function testAllMandatoryData()
dump(env('APP_ENV'));
....
它显示“本地”,我期待 phpunit.xml 中指定的“测试”
<env name="APP_ENV" value="testing"/>
编辑:附加细节 我在 Docker 容器中运行了这个 laravel 应用程序
在 docker-compose.yml 我设置了一些环境变量,例如:
environment:
- APP_ENV=local
- DB_HOST=192.168.0.22
- DB_PORT=33306
- DB_DATABASE=mydatabase
- DB_USERNAME=homestead
- DB_PASSWORD=homestead
我注意到 phpunit.xml 中的指令如下:
<env name="APP_ENV" value="testing"/>
当名称已经在 docker-compose 中时无效。
相反,如果我添加一些未在 docker-compose.yml 中定义的内容,将在 phpunit 运行时正确设置,例如:
<env name="DB_CONNECTION" value="sqlite_test"/>
结束编辑
我错过了什么?
谢谢
【问题讨论】:
我不确定您是否可以在应用程序级别覆盖容器变量?也许这些帮助:github.com/docker/compose/issues/3183, philippe.bourgau.net/… 【参考方案1】:使用
<env name="APP_ENV" value="testing" force="true"/>
<env name="CACHE_DRIVER" value="array" force="true"/>
<env name="SESSION_DRIVER" value="array" force="true"/>
<env name="QUEUE_DRIVER" value="sync" force="true"/>
<env name="DB_CONNECTION" value="sqlite_testing" force="true"/>
如果没有 force 参数,它将无法工作。看到这个问题: https://github.com/sebastianbergmann/phpunit/issues/2353 和合并后的 PR:https://github.com/sebastianbergmann/phpunit/pull/2723
【讨论】:
@koalaok 这应该是选择的答案,这样您仍然可以在 docker-compose 文件中使用这些环境参数【参考方案2】:我尝试用我找到的最佳选择来回答自己。
如果您在 docker-compose.yml 文件中设置 ENV 变量,您将无法使用 phpunit.xml 指令覆盖它们,例如:
<env name="APP_ENV" value="testing"/>
那么您应该选择从 docker-compose.yml 中删除(如本例中的)APP_ENV 变量集
并依赖 .env Laravel 文件
APP_ENV=local
通过此设置,phpunit 将能够将 APP_ENV 覆盖为“测试”
我仍然不是 100% 确定需要这种安排,所有 docker 代理版本。我拥有的另一个 Docker 版本的主机表现不同。
【讨论】:
【参考方案3】:请改用config('app.env')
。 env()
值可能会被缓存,在这种情况下 php artisan config:clear
可能会有所帮助,尽管我在从命令行环境访问 env
值时也遇到了问题。
更多信息here 和 here。
【讨论】:
谢谢,但您的任何建议都不适合我。 为什么不呢?如果您不向我们提供详细信息,任何人都无法提供帮助。 添加了我目前发现的一些细节。 使用 php artisan config:clear 为我工作,并允许我的测试针对测试数据库运行。它们应该是一种更好的测试方法,以使其始终连接到测试数据库,并且不会在不清除此配置的情况下覆盖主数据库。当我重新启动 docker setup 时,配置又回来了,所以每次我重新启动容器时都需要这样做。 仅供参考:它将是 config('app.env');。 config 函数使用点表示法。 config('APP_ENV') 将始终为空。【参考方案4】:我遇到了同样的问题,.env 变量似乎覆盖了我的 phpunit.xml 中的变量,以下是一些可行的解决方案:
-
指定运行phpunit时使用哪个phpunit.xml文件,它可能使用了错误的文件。
vendor/bin/phpunit --configuration [path to your phpunit.xml]
清理配置缓存。 php artisan config:cache
如果您在 Docker 容器中,上述操作可能不适合您。我所做的是手动删除 bootstrap/cache
文件。
希望对你有帮助!
【讨论】:
对于我的情况,我使用的是 laradock,所以我删除了我的本地引导程序/缓存运行测试并且它工作了【参考方案5】:我在使用 Docker 和 docker-compose 时遇到了同样的问题,事实上我的 docker-compose.yml 正在加载 Laravel 的 .env 文件。 所以,我通过创建一个 .env.docker 文件并设置(在 docker-compose.yml 中)来解决它:
env_file:
- .env.docker
它就像一个魅力,PHPUnit 能够选择我的 .env.testing 文件 insted .env
【讨论】:
【参考方案6】:尝试通过运行命令php artisan config:clear
清除配置缓存。这是因为您可能在运行测试之前运行了命令php artisan config:cache
,并且您的APP_ENV
被缓存为local
。
【讨论】:
【参考方案7】:我不得不求助于这个小技巧来让环境“测试”,我不得不把它放在TestCase.php
protected function setUp(): void
parent::setUp();
$this->app->detectEnvironment( function ()
return 'testing';
);
【讨论】:
【参考方案8】:对于 docker 用户,我在 composer.json
文件中添加了一个新的 test
脚本:
"test": [
"DB_CONNECTION=sqlite && DB_DATABASE=:memory: && APP_ENV=testing && phpunit --colors=always --no-coverage"
],
这个脚本只是覆盖了docker-compose.json
中定义的环境变量
【讨论】:
以上是关于为啥 phpunit 没有得到 phpunit.xml 中指定的正确 APP_ENV?的主要内容,如果未能解决你的问题,请参考以下文章
phpunit 测试返回 302 验证错误,为啥不返回 422
为啥我在测试创建相同类的 phpUnit 静态方法后得到“无法加载模拟 MyClassConsumer,类已存在”?
为啥当我运行我的 phpunit 测试时,我得到一个空响应,但 Postman 中的相同路由/用户的行为符合预期?