Maison  >  Article  >  cadre php  >  Comment utiliser l'usine de modèles dans l'application Laravel ?

Comment utiliser l'usine de modèles dans l'application Laravel ?

青灯夜游
青灯夜游avant
2022-11-28 20:26:221169parcourir

Comment utiliser Model Factory dans l'application Laravel ? L'article suivant vous présentera comment utiliser l'ingénierie des modèles Laravel dans les tests. J'espère qu'il vous sera utile !

Comment utiliser l'usine de modèles dans l'application Laravel ?

Laravel Model Factory est l'une des meilleures fonctionnalités que vous pouvez utiliser lors des tests dans votre application. Ils fournissent un moyen de définir des données prévisibles et facilement reproductibles afin que vos tests restent cohérents et contrôlables.

Commençons par un exemple simple. Nous avons une application pour bloguer, donc naturellement nous avons un modèle Post qui a le statut Publié, Rédigé ou En file d'attente. Jetons un coup d'œil au modèle Eloquent pour cet exemple :

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',
    ];
}

Comme vous pouvez le voir ici, nous avons un Enum pour la colonne status, que nous allons maintenant concevoir. L'utilisation d'énumérations ici nous permet de profiter des fonctionnalités de PHP 8.1 au lieu de chaînes simples, d'indicateurs booléens ou d'énumérations de base de données déroutantes.

 declare(strict_types=1);

namespace App\Publishing\Enums;

enum PostStatus: string
{
    case PUBLISHED = 'published';
    case DRAFT = 'draft';
    case QUEUED = 'queued';
}

Maintenant, revenons au sujet dont nous discutons ici : Model Factory. Une usine simple a l'air simple :

 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,
        ];
    }
}

Ainsi, lors de nos tests, nous pouvons désormais appeler rapidement notre post factory pour créer une publication pour nous. Voyons comment procéder :

 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');
});

Un test assez simple, mais que se passe-t-il si nos règles métier stipulent que vous ne pouvez mettre à jour que des colonnes spécifiques en fonction du type de publication ? Refactorisons notre test pour nous assurer que nous pouvons le faire :

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');
});

Parfaitement, nous pouvons passer un paramètre à la méthode create pour nous assurer que nous définissons le type correct lorsque nous le créons afin que nos règles métier ne se plaignent pas. Mais l'écrire de cette façon est un peu fastidieux, alors refactorisons un peu notre usine et ajoutons une méthode pour modifier l'état :

 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(),
            ],
        );
    }
}

Nous définissons une valeur par défaut pour l'usine afin que tous les messages nouvellement créés soient des brouillons. Nous ajoutons ensuite une méthode pour définir l'état à publier, qui utilisera la valeur Enum correcte et définira la date de publication - plus prévisible et reproductible dans un environnement de test. Voyons maintenant à quoi ressemble notre test :

 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');
});

Revenons à un test simple - donc si nous avons plusieurs tests qui souhaitent créer un brouillon de message, ils peuvent utiliser une usine. Écrivons maintenant un test pour l'état publié pour voir s'il y a des erreurs.

 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);
});

Cette fois, nous testons si nous recevons un statut d'erreur de validation lorsque nous essayons de mettre à jour un article publié. Cela garantit que nous protégeons notre contenu et appliquons des flux de travail spécifiques au sein de nos applications.

Alors que se passe-t-il si nous voulons également garantir un contenu spécifique en usine ? Nous pouvons ajouter une autre méthode pour modifier le statut si nécessaire :

 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),
            ],
        );
    }
}

Ainsi, dans nos tests, nous pouvons créer un nouveau test pour nous assurer que nous pouvons mettre à jour le brouillon du titre du message via notre 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');
});

Nous pouvons donc C'est une bonne idée de utilisez l'état d'usine pour contrôler les choses dans notre environnement de test, nous donnant autant de contrôle que possible. Cela garantira que nous sommes systématiquement préparés pour les tests ou que l’état de l’application à un moment spécifique est bien reflété.

Que devons-nous faire si nous devons créer de nombreux modèles pour nos tests ? Que devons-nous faire ? La réponse simple est de dire à l'usine :

it('lists all posts', function () {
    Post::factory(12)->create();

    getJson(
        route('api.posts.index'),
    )->assertOk()->assertJson(fn (AssertableJson $json) =>
        $json->has(12)->etc(),
    );
});

Nous créons donc 12 nouveaux messages et nous nous assurons que lorsque nous obtenons l'itinéraire d'index, nous avons 12 messages renvoyés. Au lieu de transmettre count à la méthode factory, vous pouvez également utiliser la méthode count :

Post::factory()->count(12)->create();

Cependant, dans nos applications, nous pouvons parfois vouloir exécuter les choses dans un ordre spécifique. Supposons que nous voulions que le premier soit un brouillon, mais que le second soit publié ?

 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();
    );
});

Comment utilisez-vous les usines modèles dans votre application ? Avez-vous trouvé des façons intéressantes de les utiliser ? Dites-le-nous sur Twitter !

Adresse originale : https://laravel-news.com/laravel-model-factories

Adresse de traduction : https://learnku.com/laravel/t/70290

[Recommandations associées : Tutoriel vidéo laravel

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer