Как мне заполнить базу данных в методе 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;
}
}
}