>PHP 프레임워크 >Laravel >Laravel 애플리케이션에서 모델 팩토리를 사용하는 방법은 무엇입니까?

Laravel 애플리케이션에서 모델 팩토리를 사용하는 방법은 무엇입니까?

青灯夜游
青灯夜游앞으로
2022-11-28 20:26:221204검색

Laravel 애플리케이션에서 모델 팩토리를 어떻게 사용하나요? 다음 글에서는 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 learnku.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제