Laravel アプリケーションでモデル ファクトリを使用するにはどうすればよいですか?以下の記事では、Laravel モデルエンジニアリングをテストに活用する方法を紹介しますので、ご参考になれば幸いです。
#Laravel Model Factory は、アプリケーションのテスト中に使用できる最高の機能の 1 つです。これらは、予測可能で簡単に複製可能なデータを定義する方法を提供し、テストの一貫性と制御性を維持します。
簡単な例から始めましょう。ブログ用のアプリケーションがあるので、当然、公開済み、下書き済み、またはキュー済みのステータスを持つ Post
モデルがあります。この例の Eloquent モデルを見てみましょう:
declare(strict_types=1); namespace App\Models; use App\Publishing\Enums\PostStatus; use Illuminate\Database\Model; class Post extends Model { protected $fillable = [ 'title', 'slug', 'content', 'status', 'published_at', ]; protected $casts = [ 'status' => PostStatus::class, 'published_at' => 'datetime', ]; }
ここでわかるように、ステータス列の列挙型があり、これから設計します。ここで列挙型を使用すると、プレーンな文字列、ブール型フラグ、または紛らわしいデータベース列挙型の代わりに、PHP 8.1 の機能を利用できるようになります。
declare(strict_types=1); namespace App\Publishing\Enums; enum PostStatus: string { case PUBLISHED = 'published'; case DRAFT = 'draft'; case QUEUED = 'queued'; }
さて、ここで議論しているトピック、Model Factory に戻りましょう。単純なファクトリは単純に見えます:
declare(strict_types=1); namespace Database\Factories; use App\Models\Post; use App\Publishing\Enums\PostStatus; use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Support\Arr; use Illuminate\Support\Str; class PostFactory extends Factory { protected $model = Post::class; public function definition(): array { $title = $this->faker->sentence(); $status = Arr::random(PostStatus::cases()); return [ 'title' => $title, 'slug' => Str::slug($title), 'content' => $this->faker->paragraph(), 'status' => $status->value, 'published_at' => $status === PostStatus::PUBLISHED ? now() : null, ]; } }
したがって、テストではポスト ファクトリをすぐに呼び出してポストを作成できるようになりました。これをどのように行うかを見てみましょう:
it('can update a post', function () { $post = Post::factory()->create(); putJson( route('api.posts.update', $post->slug), ['content' => 'test content', )->assertSuccessful(); expect( $post->refresh() )->content->toEqual('test content'); });
十分に単純なテストですが、ビジネス ルールで投稿タイプに基づいて特定の列のみを更新できると規定されている場合はどうなるでしょうか?テストをリファクタリングして、これを確実に実行できるようにしましょう:
it('can update a post', function () { $post = Post::factory()->create([ 'type' => PostStatus::DRAFT->value, ]); putJson( route('api.posts.update', $post->slug), ['content' => 'test content', )->assertSuccessful(); expect( $post->refresh() )->content->toEqual('test content'); });
完璧に、create メソッドにパラメータを渡して、作成時に正しい型を設定できるようにすることで、ビジネス ルールが成功するようにすることができます。文句を言わないでください。しかし、このように書くのは少し面倒なので、ファクトリを少しリファクタリングして、ステータスを変更するメソッドを追加しましょう:
declare(strict_types=1); namespace Database\Factories; use App\Models\Post; use App\Publishing\Enums\PostStatus; use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Support\Str; class PostFactory extends Factory { protected $model = Post::class; public function definition(): array { $title = $this->faker->sentence(); return [ 'title' => $title, 'slug' => Str::slug($title), 'content' => $this->faker->paragraph(), 'status' => PostStatus::DRAFT->value, 'published_at' => null, ]; } public function published(): static { return $this->state( fn (array $attributes): array => [ 'status' => PostStatus::PUBLISHED->value, 'published_at' => now(), ], ); } }
新しく作成された投稿がすべて下書きになるように、ファクトリのデフォルト値を設定します。次に、状態を公開するように設定するメソッドを追加します。これにより、正しい Enum 値が使用され、公開日が設定されます。これにより、テスト環境でより予測可能で再現可能になります。テストがどのようになるかを見てみましょう:
it('can update a post', function () { $post = Post::factory()->create(); putJson( route('api.posts.update', $post->slug), ['content' => 'test content', )->assertSuccessful(); expect( $post->refresh() )->content->toEqual('test content'); });
単純なテストに戻ります。つまり、下書き投稿を作成するテストが複数ある場合は、ファクトリを使用できます。次に、公開された状態のテストを作成して、エラーがあるかどうかを確認しましょう。
it('returns an error when trying to update a published post', function () { $post = Post::factory()->published()->create(); putJson( route('api.posts.update', $post->slug), ['content' => 'test content', )->assertStatus(Http::UNPROCESSABLE_ENTITY()); expect( $post->refresh() )->content->toEqual($post->content); });
今回は、公開された投稿を更新しようとしたときに検証エラー ステータスを受け取るかどうかをテストします。これにより、コンテンツが保護され、アプリケーション内で特定のワークフローが強制されることが保証されます。
それでは、工場内の特定のコンテンツも保証したい場合はどうなるでしょうか?必要に応じて、ステータスを変更する別のメソッドを追加できます:
declare(strict_types=1); namespace Database\Factories; use App\Models\Post; use App\Publishing\Enums\PostStatus; use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Support\Str; class PostFactory extends Factory { protected $model = Post::class; public function definition(): array { return [ 'title' => $title = $this->faker->sentence(), 'slug' => Str::slug($title), 'content' => $this->faker->paragraph(), 'status' => PostStatus::DRAFT->value, 'published_at' => null, ]; } public function published(): static { return $this->state( fn (array $attributes): array => [ 'status' => PostStatus::PUBLISHED->value, 'published_at' => now(), ], ); } public function title(string $title): static { return $this->state( fn (array $attributes): array => [ 'title' => $title, 'slug' => Str::slug($title), ], ); } }
そこで、テスト内で、API 経由で下書きの投稿タイトルを更新できることを確認するための新しいテストを作成できます:
it('can update a draft posts title', function () { $post = Post::factory()->title('test')->create(); putJson( route('api.posts.update', $post->slug), ['title' => 'new title', )->assertSuccessful(); expect( $post->refresh() )->title->toEqual('new title')->slug->toEqual('new-title'); });
そのため、工場出荷時の状態をうまく使用してテスト環境での制御を行うことができ、可能な限り多くの制御を行うことができます。そうすることで、テストの準備を一貫して行うことができ、特定の時点でのアプリケーションの状態が適切に反映されるようになります。
テスト用に多数のモデルを作成する必要がある場合はどうすればよいでしょうか?私たちは何をすべきか?簡単な答えは、ファクトリーに次のように伝えることです:
it('lists all posts', function () { Post::factory(12)->create(); getJson( route('api.posts.index'), )->assertOk()->assertJson(fn (AssertableJson $json) => $json->has(12)->etc(), ); });
したがって、12 個の新しい投稿を作成し、インデックス ルートを取得したときに 12 個の投稿が返されるようにします。 count をファクトリ メソッドに渡す代わりに、count メソッドを使用することもできます。
Post::factory()->count(12)->create();
ただし、アプリケーションでは、特定の順序で実行したい場合があります。最初のものをドラフトにし、2 番目のものを公開したいとしますか?
it('shows the correct status for the posts', function () { Post::factory() ->count(2) ->state(new Sequence( ['status' => PostStatus::DRAFT->value], ['status' => PostStatus::PUBLISHED->value], ))->create(); getJson( route('api.posts.index'), )->assertOk()->assertJson(fn (AssertableJson $json) => $json->where('id', 1) ->where('status' PostStatus::DRAFT->value) ->etc(); )->assertJson(fn (AssertableJson $json) => $json->where('id', 2) ->where('status' PostStatus::PUBLISHED->value) ->etc(); ); });
アプリケーションでモデル ファクトリをどのように使用しますか?何か素敵な使い方は見つかりましたか?ツイッターで教えてください!
#[関連する推奨事項:元のアドレス: https://laravel-news.com/laravel-model-factories
翻訳アドレス: https://learnku.com/laravel/t/70290
laravel ビデオチュートリアル]
以上がLaravelアプリケーションでモデルファクトリーを使用するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。