1
2

More than 1 year has passed since last update.

DoctrineとEloquent比較大全: テストフィクスチャを作る

Last updated at Posted at 2022-12-26

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分遅れで :sweat_smile: )完走できてホッとしています。

DoctrineはLaravelの中からも使えますし、ActiveRecordにやりにくさを感じているPHPerには、食わず嫌いせずぜひ試して見てほしいなと思います。
Doctrineを使ってみてなにかご質問あればお気軽に https://twitter.com/77web までどうぞ!!

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2