Как мне заполнить базу данных в методе setupBeforeClass в модульном тесте Laravel 4?

У меня есть тестовый класс Laravel 4 с некоторыми тестами, для которых я хочу заполнить базу данных перед запуском тестов. Использование функции setup() для повторного заполнения для каждого теста занимает слишком много времени. Однако, когда я пытаюсь заполнить в статической функции setupBeforeClass() или в конструкторе, я, очевидно, не могу использовать метод $this-> seed().

Но я также не могу использовать программные команды Artisan, потому что, когда я это делаю, я получаю следующую ошибку: PHP Fatal error: Class 'Artisan' not found in <test class name>.

Вот код, который я хотел бы использовать для заполнения:

Artisan::call('migrate:refresh');
Artisan::call('db:seed', array('--class'=>'TestSeeder');

Пожалуйста, дайте мне знать, как я могу заполнить свою базу данных один раз за тестовый класс, а не за тестовый случай

Ответ 1

"Импровизированный", но довольно чистый метод imho для достижения аналогичного эффекта заключается в том, чтобы сделать это в setUp, но запустить его только один раз (аналогично тому, как это делает setupBeforeClass):

use Illuminate\Support\Facades\Artisan;

class ExampleTest extends TestCase {

    protected static $db_inited = false;

    protected static function initDB()
    {
        echo "\n---initDB---\n"; // proof it only runs once per test TestCase class
        Artisan::call('migrate');
        // ...more db init stuff, like seeding etc.
    }

    public function setUp()
    {
        parent::setUp();

        if (!static::$db_inited) {
            static::$db_inited = true;
            static::initDB();
        }
    }

    // ...tests go here...
}

... это мое решение, и оно кажется достаточно простым и прекрасно работает, решая проблемы производительности посева и перестраивая структуру db перед каждым тестированием. Но помните, что "правильный" способ провести тестирование, что дает вам большую уверенность в том, что ваши методы тестирования не кажутся взаимозависимыми в скрытых ошибках, заключается в том, чтобы повторно засеять ваш db перед каждым методом тестирования, поэтому просто введите код посева в обычном setUp, если вы можете позволить себе штраф за исполнение (для моих тестовых случаев я не мог себе этого позволить, но ymmv...).

Ответ 2

У меня была та же проблема и решена с этим

passthru('cd ' . __DIR__ . '/../.. & php artisan migrate:refresh & db:seed --class=TestSeeder');

Ответ 3

Это лучшее решение, которое я нашел

class ExampleTest extends TestCase {
/**
 * This method is called before
 * any test of TestCase class executed
 * @return void
 */
public static function setUpBeforeClass()
{
    parent::setUpBeforeClass();
    print "\nSETTING UP DATABASE\n";
    shell_exec('php artisan migrate --seed');
}

/**
 * This method is called after
 * all tests of TestCase class executed
 * @return void
 */
public static function tearDownAfterClass()
{
    shell_exec('php artisan migrate:reset');
    print "\nDESTROYED DATABASE\n";
    parent::tearDownAfterClass();
}
/** tests goes here **/ }

Ответ 4

Вы можете сделать сейчас:

protected function setUp()
{
    parent::setUp();

    $this->seed();
}

в вашем setUp() для вашего теста.

Метод seed() принимает в качестве параметра класс сеялки.

public function seed($class = 'DatabaseSeeder')
{
    $this->artisan('db:seed', ['--class' => $class]);

    return $this;
}

Ответ 5

Эта черта является прекрасным способом сброса базы данных

<?php
namespace Tests;

use Illuminate\Support\Facades\Artisan;

trait MigrateFreshAndSeedOnce
{
    /**
     * If true, setup has run at least once.
     * @var boolean
     */
    protected static $setUpHasRunOnce = false;

    /**
     * After the first run of setUp "migrate:fresh --seed"
     * @return void
     */
    public function setUp() : void
    {
        parent::setUp();
        if (!static::$setUpHasRunOnce) {
            Artisan::call('migrate:fresh');
            Artisan::call(
                'db:seed',
                ['--class' => 'CompleteTestDbSeeder'] //add your seed class
            );
            static::$setUpHasRunOnce = true;
        }
    }
}