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

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

青灯夜游
Libérer: 2022-11-28 20:26:22
avant
1197 Les gens l'ont consulté

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',
    ];
}
Copier après la connexion

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';
}
Copier après la connexion

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,
        ];
    }
}
Copier après la connexion

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');
});
Copier après la connexion
Copier après la connexion

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');
});
Copier après la connexion

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(),
            ],
        );
    }
}
Copier après la connexion

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');
});
Copier après la connexion
Copier après la connexion

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);
});
Copier après la connexion

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),
            ],
        );
    }
}
Copier après la connexion

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');
});
Copier après la connexion

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(),
    );
});
Copier après la connexion

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();
Copier après la connexion

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();
    );
});
Copier après la connexion

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!

Étiquettes associées:
source:learnku.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal