Laravel 애플리케이션에서 모델 팩토리를 어떻게 사용하나요? 다음 글에서는 Laravel 모델 엔지니어링을 테스트에 활용하는 방법을 소개하겠습니다. 도움이 되길 바랍니다.
Laravel Model Factory는 애플리케이션에서 테스트하는 동안 사용할 수 있는 최고의 기능 중 하나입니다. 예측 가능하고 쉽게 복제할 수 있는 데이터를 정의하여 테스트가 일관되고 제어 가능하게 유지되는 방법을 제공합니다.
간단한 예부터 시작해 보겠습니다. 블로그 신청이 있으므로 당연히 게시됨, 초안 작성 또는 대기 중 상태의 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', ]; }
여기서 볼 수 있듯이 상태 열에 대한 Enum이 있으며 이제 디자인할 것입니다. 여기에서 열거형을 사용하면 일반 문자열, 부울 플래그 또는 혼란스러운 데이터베이스 열거형 대신 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'); });
완벽하게, 생성 시 올바른 유형을 설정하도록 매개변수를 생성 메소드에 전달할 수 있으므로 비즈니스 규칙이 불평하지 않습니다. 하지만 이렇게 작성하는 것은 다소 번거롭기 때문에 팩토리를 조금 리팩터링하고 상태를 수정하는 메서드를 추가해 보겠습니다.
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();
그러나 우리 애플리케이션에서는 때로는 특정 순서로 작업을 실행하고 싶을 수도 있습니다. 첫 번째 것은 초안이고 두 번째 것은 출판되기를 원한다고 가정해 보겠습니다.
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 중국어 웹사이트의 기타 관련 기사를 참조하세요!