30

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

是否有可能有类似的东西.env.testing并告诉phpunit.xml从中读取?

4

10 回答 10

21

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

如果您不想创建新文件,则必须在 php 部分中使用所需的值.env.testing指定变量,如下所示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' => env('DB_CONNECTION', 'mysql'),以默认使用 mysql,除非我指定了不同的东西,如本例所示。

于 2015-07-28T21:12:43.107 回答
20

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

更详细:

测试/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\CreatesApplicationtrait。

于 2015-08-17T14:29:51.337 回答
8

这是2019年。

我有这个问题很长时间,直到我能够弄清楚。

这是我的假设:

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

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

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

好的...

干得好:

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

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

于 2019-05-25T21:29:16.577 回答
5

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

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

DB_DATABASE=local_test_db
DB_USERNAME=root

确保您的 phpunit.xml 文件至少有一个 env var:

<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();
}
于 2015-11-19T10:29:15.893 回答
4

从这个链接

方法一

第 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

注意:如果您不想使用数据库事务,您可以使用 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();
    }
}
于 2016-01-08T23:33:22.703 回答
2

几个月来一直在努力解决这个问题,今天才遇到这个 Github 问题。从那里提出的解决方案中,您应该在 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;
}

这对我来说很好。

于 2019-07-30T18:05:34.027 回答
2

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

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

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

于 2017-03-26T10:11:11.773 回答
1

更新

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

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

所以,它将是,在 .env

DB_DATABASE=clinical_managment

在 .env.testing 中

DB_DATABASE=clinical_managment_testing

然后,明确配置。

php artisan config:clear

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

于 2019-11-14T03:56:46.173 回答
1

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

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

APP_ENV=testing php artisan migrate --database=sqlite_testing
于 2017-09-30T10:37:25.627 回答
0

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

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

于 2015-07-28T16:56:41.130 回答