Тест Laravel 5.5 PHPunit — корень фасада не установлен.

Когда я выполняю попытку/поймать на DB::Connection()->getPdo();, я получаю сообщение об ошибке Корень фасада не был установлен. Я полагаю, что это происходило и с фасадами Schema до того, как я попытался добавить попытку/поймать. Каталог с тестами, конечно, находится за пределами каталога с приложением, и у меня есть ощущение, что это как-то связано с этим, но мне не удалось это выяснить.

Вот тестовый класс, в котором это происходит:

<?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');
        });
    }
}

person Justin Anthony    schedule 27.09.2017    source источник
comment
Немного беспокоит то, что вы строите схему внутри своего модульного теста. Обычно вы хотите иметь предварительно созданную базу данных, а затем использовать трейт Illuminate\Foundation\Testing\DatabaseTransactions, чтобы убедиться, что что-то отменяется после завершения модульного теста.   -  person amphetamachine    schedule 18.12.2018


Ответы (2)


Дело в том, что вы не можете сделать это в setUpBeforeClass, потому что многие вещи запускаются в методе setUp. Если вы посмотрите на этот порядок выполнения, вы увидите, что setUpBeforeClass запускается перед методом setUp, а класс TestCase делает много вещей в методе 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
}
person Marcin Nabiałek    schedule 27.09.2017
comment
Я просмотрел функцию setUp базового теста, и на самом деле это пустая функция. - person Justin Anthony; 27.09.2017
comment
@JustinAnthony Вы смотрели Illuminate\Foundation\Testing\TestCase класс? В этом классе у вас есть метод setUp с содержимым, которое я показал - person Marcin Nabiałek; 27.09.2017
comment
Упс, я зашел в родительский setUp этого Фонда. Зашел слишком глубоко. На самом деле похоже, что это сделало это, помещая мои вызовы схемы в setUp вместо setUpBeforeClass. Тем временем я нашел другое решение, использующее Capsule. Есть ли у вас мнение о том, какой из двух методов лучше использовать? - person Justin Anthony; 27.09.2017
comment
Я никогда не слышала о капсулах. Я использую setUp для таких вещей, но обычно нет смысла создавать таблицы вручную, потому что вы обычно используете черты базы данных для создания схемы базы данных из миграций. - person Marcin Nabiałek; 27.09.2017
comment
Я столкнулся с проблемой, когда мы используем более новую версию mySQL, где мы используем типы столбцов json, которые несовместимы с sqlite, поэтому мне нужно сделать подмножество миграции, специально предназначенное для тестирования. Я хотел сделать так, чтобы я создавал таблицы только один раз для каждого набора тестов, но заполнял их перед началом каждого теста. Приводит ли необходимость запуска ложных миграций в setUp к значительным задержкам во время тестирования? - person Justin Anthony; 27.09.2017
comment
Просто протестируйте и вы увидите - person Marcin Nabiałek; 27.09.2017

Для всех, кому интересно узнать о другом методе, который я нашел для работы с использованием 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
        ]);
    }
}
person Justin Anthony    schedule 27.09.2017