day25(から2日遅れの!)今日はテストフィクスチャの作り方を見ていきます!
Doctrine
Fixtures/AuthorLoader.php
<?php
declare(strict_types=1);
namespace App\Fixtures;
use App\Entity\Author;
use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Persistence\ObjectManager;
class AuthorLoader implements FixtureInterface
{
public function load(ObjectManager $manager)
{
for ($i = 1; $i <= 5; $i++) {
$author = new Author();
$author->setName('author'.$i);
$manager->persist($author);
}
$manager->flush();
}
}
<?php
declare(strict_types=1);
use App\Entity\Author;
use App\Fixtures\AuthorLoader;
use Doctrine\Common\DataFixtures\Executor\ORMExecutor;
use Doctrine\Common\DataFixtures\Loader;
use Doctrine\Common\DataFixtures\Purger\ORMPurger;
use Doctrine\ORM\EntityManagerInterface;
require __DIR__.'/../vendor/autoload.php';
/** @var EntityManagerInterface $entityManager */
$entityManager = require __DIR__.'/bootstrap.php';
$loader = new Loader();
$loader->addFixture(new AuthorLoader());
$executor = new ORMExecutor($entityManager, new ORMPurger($entityManager));
$executor->execute($loader->getFixtures());
$entityManager->getRepository(Author::class)->findAll(); // 5件登録されている
- doctrine/data-fixturesを使います。
- 愚直にエンティティを作ってpersist, flushするという使い心地のため、コード量も多めでやや使いにくいです。
- それをカバーするために(?)Symfonyアプリケーションのテストフィクスチャとしてはサードパーティのnelmio/alice + liip/test-fixtures-bundle を活用するのが一般的でした。
- 最近zenstruck/foundryという新しいfixtureライブラリが作られ、こちらはEloquentのfactoryとやや似た使い心地となっています。詳しい使い方はこちら。 https://tech.quartetcom.co.jp/2021/12/20/foundry-the-new-fixtures-for-functional-testing/
Eloquent
database/factories/AuthorFactory.php
<?php
namespace Database\Factories;
use App\Models\Author;
use Illuminate\Database\Eloquent\Factories\Factory;
class AuthorFactory extends Factory
{
protected $model = Author::class;
/**
* モデルのデフォルト状態の定義
*
* @return array
*/
public function definition(): array
{
return [
'name' => $this->faker->name(),
];
}
protected static function newFactory()
{
return self::new();
}
}
<?php
declare(strict_types=1);
use App\Models\Author;
require __DIR__.'/../vendor/autoload.php';
require __DIR__.'/bootstrap.php';
$author = Author::factory()->create();
- 所定のファクトリクラスを作り、モデルに紐付けておくことで、モデルからファクトリを呼び出せます。
- factory()->create()によって内部でEloquentによってsave()が呼び出されてDB書き込みが行われるため、UnitTestではうっかり使わないように気をつけましょう。
あとがき
Eloquentに比べてDoctrineの日本語情報が少ない・Doctrineの日本語情報が圧倒的に「Symfonyの中での使い方」に偏っている、というのを少しでも補いたいと思い、今年は1人アドベントカレンダーに挑戦してみました。
無事に(24時間10分遅れで )完走できてホッとしています。
DoctrineはLaravelの中からも使えますし、ActiveRecordにやりにくさを感じているPHPerには、食わず嫌いせずぜひ試して見てほしいなと思います。
Doctrineを使ってみてなにかご質問あればお気軽に https://twitter.com/77web までどうぞ!!