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

Laravel 8测试时config()函数取值异常问题排查

问题:Laravel 8测试时env()与config()取值不一致

环境与异常现象

基于Laravel 8 + Laravel Sail的应用,执行sail artisan test运行测试时出现异常:

  • env()函数能正确获取phpunit.xml中覆盖的配置值
  • config()函数却读取到.env文件里的旧值

相关配置

phpunit.xml 配置片段

<php>
    <server name="APP_ENV" value="testing" force="true"/>
    <server name="BCRYPT_ROUNDS" value="4"/>
    <server name="CACHE_DRIVER" value="array"/>

    <server name="DB_CONNECTION" value="sqlite" force="true"/>
    <server name="DB_DATABASE" value=":memory:"/>

    <server name="DB_LEGACY_CONNECTION" value="sqlite" />
    <server name="DB_LEGACY_DATABASE" value=":memory:" />
</php>

.env 配置片段

APP_PORT=49200
APP_NAME=Laravel
APP_ENV=local

DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
FORWARD_DB_PORT=33061
DB_DATABASE=lb_backend
DB_USERNAME=sail
DB_PASSWORD=sail

测试代码与输出

Pest测试的beforeEach方法中打印变量:

beforeEach(function () {
    $env_vars = [
        env('APP_ENV', 'production'),  // 返回testing
        config('app.env'),             // 返回local

        env('DB_CONNECTION', 'mysql'),  // 返回sqlite
        config('database.default')      // 返回mysql
    ];
    fwrite(STDERR, print_r($env_vars, TRUE));
    $this->usingInMemoryDatabase();     // 返回false,内部调用config('database.default')

    // ...
});

核心配置文件片段

config/app.php

<?php

return [

    // ...

    /*
    |--------------------------------------------------------------------------
    | Application Environment
    |--------------------------------------------------------------------------
    |
    | This value determines the "environment" your application is currently
    | running in. This may determine how you prefer to configure various
    | services the application utilizes. Set this in your ".env" file.
    |
    */

    'env' => env('APP_ENV', 'production'),

    // ...
];

config/database.php

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Default Database Connection Name
    |--------------------------------------------------------------------------
    |
    | Here you may specify which of the database connections below you wish
    | to use as your default connection for all database work. Of course
    | you may use many connections at once using the Database library.
    |
    */

    'default' => env('DB_CONNECTION', 'mysql'),

    // ...
];

原因与解决方案

这不是Laravel或Sail的Bug,是配置加载顺序导致的问题:
Laravel启动时会先加载.env文件,紧接着加载所有config/*.php配置文件,此时配置文件会把当时的环境变量值缓存到配置数组中。而phpunit.xml里的<server>配置是在Laravel应用初始化完成后才设置的环境变量,所以config()读取的是初始化时缓存的旧值,而env()直接读取当前环境变量,因此能拿到新值。

解决方法

方法一:测试时重新初始化应用

在beforeEach中调用refreshApplication(),强制重新加载配置:

beforeEach(function () {
    $this->refreshApplication();
    // 后续测试代码...
});

方法二:使用.env.testing文件

创建.env.testing文件,写入测试环境专属配置:

APP_ENV=testing
DB_CONNECTION=sqlite
DB_DATABASE=:memory:
# 其他测试环境需要的配置

Laravel运行测试时会自动优先加载.env.testing,无需修改phpunit.xml,配置加载时就能读取到正确的值。

方法三:调整phpunit.xml的bootstrap流程

确保phpunit的bootstrap文件在Laravel初始化前就设置好环境变量,不过前两种方法更简单直接。

内容的提问来源于stack exchange,提问作者C. Celora

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 11:30:59