You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建多态关联工厂用于PHPUnit测试?解决无法创建多评论问题

Fixing Your Comment Creation Test & Setting Up Polymorphic Factories

Alright, let’s tackle your two questions step by step—first getting your test to create multiple comments, then setting up polymorphic factories for your PHPUnit tests.


1. Fixing the "Can’t Create Multiple Comments" Test Issue

Looking at your current test code, you’re only sending one POST request to create a comment, so assertCount(1) is actually working as expected. To create multiple comments, you need to simulate multiple user submissions, and also make sure you’re fetching the fresh version of the article from the database (since the in-memory model won’t auto-update its relationships).

Here’s the adjusted test:

/** @test */ 
public function an_authenticated_user_can_create_multiple_comments_on_a_post(){ 
    $user = $this->signIn(); 
    $article = factory('App\Article')->create(); 

    // Simulate submitting 3 separate comments
    for ($i = 0; $i < 3; $i++) {
        $this->post(route('articles.comments.store', $article->slug), [ 
            'comment' => $this->faker->sentence, 
        ]); 
    }

    // Use fresh() to pull the updated article from the database
    $this->assertCount(3, $article->fresh()->comments); 
}

Also, double-check your controller’s store method to ensure it’s correctly handling the polymorphic association. It should look something like this (assuming you’ve defined the relationships properly):

// In your CommentsController
public function store(Article $article)
{
    auth()->user()->comments()->create([
        'body' => request('comment'),
        'commentable_id' => $article->id,
        'commentable_type' => Article::class,
    ]);

    return back();
}

// Or even cleaner, using the article's comments relationship:
public function store(Article $article)
{
    $article->comments()->create([
        'body' => request('comment'),
        'user_id' => auth()->id(),
    ]);

    return back();
}

2. Creating Polymorphic Factories for Tests

Polymorphic associations in factories are straightforward once you set them up correctly. Let’s break this down based on your Article and Comment models.

First, Confirm Your Model Relationships

Make sure your models have the correct polymorphic relationships defined:

// App\Comment.php
namespace App;

use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
    protected $fillable = ['body', 'user_id'];

    public function commentable()
    {
        return $this->morphTo();
    }

    public function user()
    {
        return $this->belongsTo(User::class);
    }
}
// App\Article.php
namespace App;

use Illuminate\Database\Eloquent\Model;

class Article extends Model
{
    protected $fillable = ['title', 'slug', 'body', 'user_id'];

    public function comments()
    {
        return $this->morphMany(Comment::class, 'commentable');
    }
}

Option 1: Basic Factory with States

Define a base Comment factory, then use states to specify which polymorphic model it should belong to. This keeps your factory flexible.

// database/factories/CommentFactory.php
use App\Comment;
use App\Article;
use App\User;
use Faker\Generator as Faker;

$factory->define(Comment::class, function (Faker $faker) {
    return [
        'body' => $faker->paragraph,
        'user_id' => factory(User::class), // Associate with a random user
    ];
});

// State for comments linked to Articles
$factory->state(Comment::class, 'for_article', function (Faker $faker) {
    return [
        'commentable_id' => factory(Article::class),
        'commentable_type' => Article::class,
    ];
});

Usage in Tests:

// Create a single comment linked to an article
$comment = factory(Comment::class)->state('for_article')->create();

// Create 5 comments all linked to the same article
$article = factory(Article::class)->create();
$comments = factory(Comment::class, 5)->create([
    'commentable_id' => $article->id,
    'commentable_type' => Article::class,
]);

Option 2: Auto-Associate with Random Polymorphic Models

If you want your factory to randomly link comments to different polymorphic models (e.g., Article and Post later), you can do this:

// database/factories/CommentFactory.php
$factory->define(Comment::class, function (Faker $faker) {
    // List all possible commentable models
    $commentableTypes = [Article::class]; // Add others like Post::class later
    $commentableType = $faker->randomElement($commentableTypes);

    return [
        'body' => $faker->paragraph,
        'user_id' => factory(User::class),
        'commentable_id' => factory($commentableType),
        'commentable_type' => $commentableType,
    ];
});

Option 3: Attach Comments to Articles in the Article Factory

You can also set up your Article factory to automatically create comments when generating an article, using afterCreatingState:

// database/factories/ArticleFactory.php
use App\Article;
use App\User;
use Faker\Generator as Faker;

$factory->define(Article::class, function (Faker $faker) {
    return [
        'title' => $faker->sentence,
        'slug' => $faker->slug,
        'body' => $faker->paragraphs(3, true),
        'user_id' => factory(User::class),
    ];
});

// State to create an article with 3 comments
$factory->state(Article::class, 'with_comments', function (Faker $faker) {
    return [];
})->afterCreatingState(Article::class, 'with_comments', function ($article, $faker) {
    factory(App\Comment::class, 3)->create([
        'commentable_id' => $article->id,
        'commentable_type' => Article::class,
    ]);
});

Usage in Tests:

$article = factory(Article::class)->state('with_comments')->create();
$this->assertCount(3, $article->comments);

内容的提问来源于stack exchange,提问作者rakesh shrestha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:52:40