我有一个.env
包含我的数据库连接详细信息的文件,这对于 Laravel 5 来说是正常的。我想覆盖这些以进行测试,我可以在phpunit.xml
. 然而,这样做似乎违背了.env
不提交环境配置的理念,尤其是密码。
是否有可能有类似的东西.env.testing
并告诉phpunit.xml
从中读取?
将您复制.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,除非我指定了不同的东西,如本例所示。
您可以覆盖.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\CreatesApplication
trait。
这是2019年。
我有这个问题很长时间,直到我能够弄清楚。
这是我的假设:
如果您还发现很难让您的 PHPUnit.xml 与您的 .env.testing 文件对话,那么您可能正在使用 PHPStorm!
如果这是真的,请继续阅读。
如果没有,不……这无济于事。
好的...
干得好:
这样做是为了使您在 xml 文件中的所有更改生效。所以,继续,创建 .env.testing 文件,创建您喜欢的用于测试的数据库配置变量……然后再次尝试运行您的测试!
在你的开发机器上创建一个本地数据库,例如'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();
}
从这个链接
方法一
第 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();
}
}
几个月来一直在努力解决这个问题,今天才遇到这个 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;
}
这对我来说很好。
在您的 app.php 中更改 Dotenv 部分
$envFile = 'testing' === env('APP_ENV') ? '.env.testing' : null;
try {
(new Dotenv\Dotenv(__DIR__ . '/../', $envFile))->load();
} catch (Dotenv\Exception\InvalidPathException $e) {
//
}
这将起作用,因此 PHPUnit 在加载您的应用程序之前更改了环境。所以如果运行测试,您将在测试时拥有环境
更新
对于 Laravel 5.8 用户,您可以.env.testing
在项目的根目录中创建一个文件。
使用不同的数据库,例如 my_app_testing。
所以,它将是,在 .env
DB_DATABASE=clinical_managment
在 .env.testing 中
DB_DATABASE=clinical_managment_testing
然后,明确配置。
php artisan config:clear
重新运行测试。在我的设置中,它可以工作。
我完成了@Sambhu Singh 回答中的所有步骤,并遵循了他的链接。但在 L5.5 中对我不起作用
迁移时,在 artisan 命令前面将 APP_ENV 添加/设置为“测试”对我有用:
APP_ENV=testing php artisan migrate --database=sqlite_testing
除了在单元测试开始之前将 .env.testing 临时重命名为 .env 之外,我想不出别的办法。
您可以在 bootstrap/autoload.php 中添加一些逻辑,因为这是 phpunit 在加载应用程序之前使用的引导文件。