【问题标题】:How to specify a different .env file for phpunit in Laravel 5?如何在 Laravel 5 中为 phpunit 指定不同的 .env 文件?
【发布时间】:2015-10-19 08:09:29
【问题描述】:

我有一个包含我的数据库连接详细信息的 .env 文件,这对于 Laravel 5 来说是正常的。我想覆盖这些以进行测试,我可以在 phpunit.xml 中执行此操作。但是,这样做似乎违背了.env 的理念,即不提交环境配置,尤其是密码。

是否可以有类似.env.testing 的内容并告诉phpunit.xml 从中读取?

【问题讨论】:

  • 这可能会有所帮助:stackoverflow.com/a/27986561/2433843
  • 我刚刚更新了我的答案,希望对您有所帮助
  • 看看我的帖子here - 可能会给你一些线索。
  • “.env 的理念是不提交环境配置”,为什么不直接在测试环境配置环境变量呢?
  • @SanderVisser 因为它不是一个单独的环境。我在开发网站的同一台机器上运行测试。

标签: php laravel laravel-5 phpunit phpdotenv


【解决方案1】:

将您的.env 复制到.env.testing,然后编辑.env.testing 文件并更改APP_ENV 参数使其像这样APP_ENV=testing 这样您就可以在这个新文件中指定您的设置

如果您不想创建新的 .env.testing 文件,则必须在 php 部分的 phpunit.xml 中使用所需的值指定变量,如下所示

<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"/>
    <env name="DB_DATABASE" value="testing"/>
</php>

只需使用名称部分中的键值和值部分中该键的值。

对于这个例子,我指定 phpunit 使用名为 testing 的 sqlite 数据库。

顺便说一下,我在 config/database.php 中添加了这个 'default' =&gt; env('DB_CONNECTION', 'mysql'), 默认使用 mysql,除非我指定了不同的东西,如本例所示。

【讨论】:

  • 我知道你可以在 phpunit.xml 中做到这一点,我在我的问题中说过。我要避免的是在那里指定数据库连接详细信息,然后我将提交它们。
  • 虽然这只是为了测试目的,但如果将值放在 phpunit.xml 中并不重要,我建议使用另一个数据库引擎,如 sqlite 或完全不同的东西您在开发中使用,在我的情况下,我这样做并且我从不将凭据提交到我的真实数据库,只是将凭据提交到测试数据库,在这种情况下使用 sqlite。您应该查看此类问题的文档,因为这是正确的方法。
  • 问题在于我在代码中使用了 SQL 查询(不使用 ORM),因此查询在不同的数据库引擎上可能会略有不同。
  • .env.testing 是 Laravel 的约定?
  • 是的,您实际上可以查看文档以了解有关 .env.testing 文件 laravel.com/docs/5.8/testing 的更多信息
【解决方案2】:

您可以覆盖在您的 TestCase 文件中使用的 .env 文件,在该文件中启动框架进行测试。

更具体:

测试/TestCase.php

/**
 * Creates the application.
 *
 * @return \Illuminate\Foundation\Application
 */
public function createApplication()
{
    /* @var \Illuminate\Foundation\Application $app */
    $app = require __DIR__ . '/../bootstrap/app.php';

    $app->loadEnvironmentFrom('.env.testing'); // specify the file to use for environment, must be run before boostrap

    $app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();

    return $app;
}

所有扩展TestCase 的测试都将使用这个配置文件。

请注意,phpunit.xml 中定义的任何设置都将覆盖此配置。

更新

从 Laravel5.4 开始,createApplication 函数在 tests\TestCase 中不再存在。它已移至tests\CreatesApplication trait。

【讨论】:

  • 您的回答看起来很有希望,但由于某种原因,它仍在加载 .env。
  • @SeánHayes 确保你运行 $app-&gt;loadEnvironmentFrom(..) before boostrap() 否则它将使用默认的 .env
  • 这似乎是一种不好的做法。
  • @DimitriAcosta,你为什么这么认为?
  • 因为您不应该更改测试代码。
【解决方案3】:

这是 2019 年。

我一直有这个问题,直到我能够弄清楚。

这是我的假设:

如果您还发现很难让您的 PHPUnit.xml 与您的 .env.testing 文件对话,那么您可能正在使用 PHPStorm!

如果这是真的,请继续阅读。

如果没有,不...这无济于事。

好的...

给你:

  1. 转到 PHPStorm 的设置,或者只需按 Ctrl + Alt + S。
  2. 转到语言和框架 >> PHP >> 测试框架
  3. 在 Test Runner 选项卡下,单击 Default configuration file 并选择(通过单击文件夹图标)项目的 PHPUnit.xml 文件的路径。

这样做是为了使您在 xml 文件中的所有更改生效。 所以,继续吧,创建 .env.testing 文件,创建您喜欢的用于测试的 DB 配置变量……然后再次尝试运行您的测试!

【讨论】:

    【解决方案4】:

    在您的开发机器上创建一个本地数据库,例如'local_test_db'

    创建一个新的 .env.testing 文件。

    DB_DATABASE=local_test_db
    DB_USERNAME=root
    

    确保你的 phpunit.xml 文件至少有这个环境变量:

    <php>
        <env name="APP_ENV" value="testing"/>
    </php>
    

    最后,您的基本测试用例 (TestCase.php) 应该运行迁移以使用表填充数据库:

    public function createApplication()
    {
    
        $app = require __DIR__.'/../bootstrap/app.php';
    
        $app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();
    
        return $app;
    }
    
    
    public function setUp()
    {
        parent::setUp();
        Artisan::call('migrate');
    }
    
    public function tearDown()
    {
        Artisan::call('migrate:reset');
        parent::tearDown();
    }
    

    【讨论】:

    • “确保你的 phpunit.xml 文件至少有这个 env var...” 这是 Laravel 文档和这里的其他答案没有明确说明的一个神奇的部分。非常感谢!
    • @JoelMellon 很乐意为您提供帮助。
    【解决方案5】:

    来自link

    方法一

    步骤 1:在 Database/Config.php 上创建新的测试数据库连接,如下所示:

    return [
        ... 
    
        'default' => env('DB_CONNECTION', 'db'),    
    
        'connections' => [
            'sqlite_testing_db' => [
                'driver' => 'sqlite',
                'database' => storage_path().'/testing_database.sqlite',           
                'prefix' => '',
            ],
    
            /**************** OR ******************/
    
            'testing_db' => [
                'driver' => 'mysql',
                'host' => env('TEST_DB_HOST', 'localhost'),
                'database' => env('TEST_DB_DATABASE', 'forge'),
                'username' => env('TEST_DB_USERNAME', 'forge'),
                'password' => env('TEST_DB_PASSWORD', ''),
                'charset' => 'utf8',
                'collation' => 'utf8_unicode_ci',
                'prefix' => '',
                'strict' => false,
            ],
    
            /** Production or database DB **/
            'db' => [
                'driver' => 'mysql',
                'host' => env('TEST_DB_HOST', 'localhost'),
                'database' => env('TEST_DB_DATABASE', 'forge'),
                'username' => env('TEST_DB_USERNAME', 'forge'),
                'password' => env('TEST_DB_PASSWORD', ''),
                'charset' => 'utf8',
                'collation' => 'utf8_unicode_ci',
                'prefix' => '',
                'strict' => false,
            ],
        ],
    ];
    

    第 2 步:在 .env 文件中指定数据库凭据

    TEST_DB_HOST=localhost
    TEST_DB_DATABASE=laravel
    TEST_DB_USERNAME=root
    TEST_DB_PASSWORD=rootwdp
    

    第 3 步:指定要在 phpunit.xml 上使用的测试数据库连接。

    <env name="DB_CONNECTION" value="testing_db"/>
              OR Below If you prefer sqlite
    <env name="DB_CONNECTION" value="sqlite_testing_db"/>                
    

    第 4 步:将数据库迁移到这个新的测试数据库 - 如果您选择使用数据库事务来回滚表上的插入。

    php artisan migrate --database=testing_db
    
    //If using sqlite
    touch storage/testing_database.sqlite
    php artisan migrate --database=sqlite_testing
    

    第 5 步:现在,使用数据库事务的单元测试如下所示:

    <?php
    
    use App\User;
    use Illuminate\Foundation\Testing\DatabaseTransactions;
    
    class UserTest extends TestCase
    {
        use DatabaseTransactions;
    
        /** @test */
        function it_test_user_can_be_saved()
        {
            factory(User::class, 2)->create();
    
            $users = User::all();
    
            $this->assertEquals(2, $users->count());
        }
    }
    
    //Run Php Unit
    -> vendor/bin/phpunit --color tests/acceptance/model/UserTest.php
    

    注意:如果你不想使用Database Transaction,你可以使用TestCase.php类的setup和teardown方法来迁移和回滚数据库,如下所示:

    <?php
    
    use Illuminate\Support\Facades\Artisan;
    
    class TestCase extends Illuminate\Foundation\Testing\TestCase
    {
        ...
    
        public function setUp()
        {
            parent::setUp();
            Artisan::call('migrate');
        }
    
        public function tearDown()
        {
            Artisan::call('migrate:reset');
            parent::tearDown();
        }
    }
    

    【讨论】:

    • 我喜欢这种方式更好更合理
    【解决方案6】:

    在您的 app.php 中更改 Dotenv 部分

    $envFile = 'testing' === env('APP_ENV') ? '.env.testing' : null;
    try {
        (new Dotenv\Dotenv(__DIR__ . '/../', $envFile))->load();
    } catch (Dotenv\Exception\InvalidPathException $e) {
        //
    }
    

    这将起作用,因此 PHPUnit 在加载您的应用程序之前会更改环境。所以如果运行测试,您将在测试时拥有环境

    【讨论】:

    • 谢谢,这个答案适用于 Lumen v5.6,其他的则不行(也许在引导 Lumen 与 Laravel 时存在一些差异)
    【解决方案7】:

    几个月来一直在为此苦苦挣扎,今天才遇到this Github issue。 从那里提出的解决方案中,您应该在 CreatesApplication.php 文件中执行以下操作(删除缓存的配置以让 Laravel 加载测试环境):

    /**
     * Creates the application.
     *
     * @return \Illuminate\Foundation\Application
     */
    public function createApplication()
    {
        $app = require __DIR__.'/../bootstrap/app.php';
    
        $app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();
    
        $this->clearCache(); // NEW LINE -- Testing doesn't work properly with cached stuff.
    
        return $app;
    }
    
    /**
     * Clears Laravel Cache.
     */
    protected function clearCache()
    {
        $commands = ['clear-compiled', 'cache:clear', 'view:clear', 'config:clear', 'route:clear'];
        foreach ($commands as $command) {
            \Illuminate\Support\Facades\Artisan::call($command);
        }
    }
    

    如果您在上述修改后仍然遇到此问题,您可以通过以下方式重新构建整个应用程序来进一步:

    public function createApplication()
    {
        $createApp = function() {
            $app = require __DIR__.'/../bootstrap/app.php';
            $app->make(Kernel::class)->bootstrap();
            return $app;
        };
    
        $app = $createApp();
        if ($app->environment() !== 'testing') {
            $this->clearCache();
            $app = $createApp();
        }
    
        return $app;
    }
    

    这对我来说很好用。

    【讨论】:

      【解决方案8】:

      我完成了@Sambhu Singh 回答中的所有步骤,并遵循了他的链接。 但在 L5.5 中对我不起作用

      迁移时,在 artisan 命令前面将 APP_ENV 添加/设置为“测试”对我有用:

      APP_ENV=testing php artisan migrate --database=sqlite_testing
      

      【讨论】:

        【解决方案9】:

        更新

        对于 Laravel 5.8 用户,您可以在项目的根目录中创建一个 .env.testing 文件。

        使用不同的数据库,例如 my_app_testing。

        所以,它会在 .env 中

        DB_DATABASE=clinical_managment
        

        在 .env.testing 中

        DB_DATABASE=clinical_managment_testing
        

        然后,清除配置。

        php artisan config:clear
        

        重新运行测试。在我的设置中,它可以工作。

        【讨论】:

          【解决方案10】:

          除了在单元测试开始之前暂时将 .env.testing 重命名为 .env 之外,我想不出别的办法。

          您可以在 bootstrap/autoload.php 中添加一些逻辑,因为这是 phpunit 在加载应用程序之前使用的引导文件。

          【讨论】:

            猜你喜欢
            • 2015-05-07
            • 2015-03-18
            • 2020-10-08
            • 1970-01-01
            • 2017-05-03
            • 2021-05-02
            • 2014-12-09
            • 2015-07-07
            • 1970-01-01
            相关资源
            最近更新 更多