Laravel 5.5 PHP 单元测试 - "A facade root has not been set."
Laravel 5.5 PHPunit Test - "A facade root has not been set."
当我在 DB::Connection()->getPdo();
上执行 try/catch 时,我得到错误 A facade root has not been set. 我相信它发生在在我尝试添加 try/catch 之前,Schema
立面也是如此。 tests目录当然在app目录之外,我感觉跟那个有关系,但是我没弄清楚。
这是测试 class 发生这种情况的地方:
<?php
namespace Tests\Models;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;
use App\Models\Discussion;
use App\User;
use Business\Database\Model;
use Illuminate\Database\Schema\Blueprint;
use Tests\TestCase;
class DiscussionModelTest extends TestCase
{
/**
* Create the tables this model needs for testing.
*/
public static function setUpBeforeClass()
{
try {
DB::connection()->getPdo();
} catch(\Exception $e) {
die($e->getMessage());
}
Schema::create('discussions', function (Blueprint $table) {
$table->integer('id');
$table->integer('user_id');
$table->foreign('user_id')->references('id')->on('users');
});
Schema::create('users', function (Blueprint $table) {
$table->integer('id');
});
}
}
问题是您不能在 setUpBeforeClass 中执行此操作,因为 setUp
方法中有很多内容 运行。如果您查看 this order of run,您会看到 setUpBeforeClass
在 setUp
方法之前是 运行,而 TestCase class 在 setUp
方法中做了很多事情。它看起来像这样:
protected function setUp()
{
if (! $this->app) {
$this->refreshApplication();
}
$this->setUpTraits();
foreach ($this->afterApplicationCreatedCallbacks as $callback) {
call_user_func($callback);
}
Facade::clearResolvedInstances();
Model::setEventDispatcher($this->app['events']);
$this->setUpHasRun = true;
}
所以您应该做的是使用您自己的实现创建自己的 setUp
和 tearDown
方法,如下所示:
protected function setUp()
{
parent::setUp();
// your code goes here
}
protected function tearDown()
{
parent::tearDown();
// your code goes here
}
如果其他人对我发现的使用 Capsule 的其他方法感到好奇,请查看代码。这将适用于 setUpBeforeClass()
和 setUp()
。这可以而且应该更抽象,但这是它的要点。
use Illuminate\Database\Capsule\Manager as Capsule;
class DiscussionModelTest extends TestCase
{
/**
* Create the tables this model needs for testing.
*/
public static function setUpBeforeClass()
{
$capsule = new Capsule;
$capsule->addConnection([
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => '',
]);
$capsule->setAsGlobal();
$capsule->bootEloquent();
Capsule::schema()->create('discussions', function (Blueprint $table) {
$table->integer('id');
$table->integer('user_id');
$table->foreign('user_id')->references('id')->on('users');
});
Capsule::schema()->create('users', function (Blueprint $table) {
$table->integer('id');
});
// Seed the faux DB
Model::unguard();
User::create([
'id' => 13
]);
Discussion::create([
'id' => 5,
'user_id' => 13
]);
}
}
你不应该这样做,因为功能测试会扩展测试目录中的 TestCase class 而不是 PHPUnit 的。
删除:
use PHPUnit\Framework\TestCase;
并将其替换为:
use Tests\TestCase;
当我在 DB::Connection()->getPdo();
上执行 try/catch 时,我得到错误 A facade root has not been set. 我相信它发生在在我尝试添加 try/catch 之前,Schema
立面也是如此。 tests目录当然在app目录之外,我感觉跟那个有关系,但是我没弄清楚。
这是测试 class 发生这种情况的地方:
<?php
namespace Tests\Models;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;
use App\Models\Discussion;
use App\User;
use Business\Database\Model;
use Illuminate\Database\Schema\Blueprint;
use Tests\TestCase;
class DiscussionModelTest extends TestCase
{
/**
* Create the tables this model needs for testing.
*/
public static function setUpBeforeClass()
{
try {
DB::connection()->getPdo();
} catch(\Exception $e) {
die($e->getMessage());
}
Schema::create('discussions', function (Blueprint $table) {
$table->integer('id');
$table->integer('user_id');
$table->foreign('user_id')->references('id')->on('users');
});
Schema::create('users', function (Blueprint $table) {
$table->integer('id');
});
}
}
问题是您不能在 setUpBeforeClass 中执行此操作,因为 setUp
方法中有很多内容 运行。如果您查看 this order of run,您会看到 setUpBeforeClass
在 setUp
方法之前是 运行,而 TestCase class 在 setUp
方法中做了很多事情。它看起来像这样:
protected function setUp()
{
if (! $this->app) {
$this->refreshApplication();
}
$this->setUpTraits();
foreach ($this->afterApplicationCreatedCallbacks as $callback) {
call_user_func($callback);
}
Facade::clearResolvedInstances();
Model::setEventDispatcher($this->app['events']);
$this->setUpHasRun = true;
}
所以您应该做的是使用您自己的实现创建自己的 setUp
和 tearDown
方法,如下所示:
protected function setUp()
{
parent::setUp();
// your code goes here
}
protected function tearDown()
{
parent::tearDown();
// your code goes here
}
如果其他人对我发现的使用 Capsule 的其他方法感到好奇,请查看代码。这将适用于 setUpBeforeClass()
和 setUp()
。这可以而且应该更抽象,但这是它的要点。
use Illuminate\Database\Capsule\Manager as Capsule;
class DiscussionModelTest extends TestCase
{
/**
* Create the tables this model needs for testing.
*/
public static function setUpBeforeClass()
{
$capsule = new Capsule;
$capsule->addConnection([
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => '',
]);
$capsule->setAsGlobal();
$capsule->bootEloquent();
Capsule::schema()->create('discussions', function (Blueprint $table) {
$table->integer('id');
$table->integer('user_id');
$table->foreign('user_id')->references('id')->on('users');
});
Capsule::schema()->create('users', function (Blueprint $table) {
$table->integer('id');
});
// Seed the faux DB
Model::unguard();
User::create([
'id' => 13
]);
Discussion::create([
'id' => 5,
'user_id' => 13
]);
}
}
你不应该这样做,因为功能测试会扩展测试目录中的 TestCase class 而不是 PHPUnit 的。
删除:
use PHPUnit\Framework\TestCase;
并将其替换为:
use Tests\TestCase;