laravel 单元测试溢出异常:未找到唯一值的最大重试次数达到10000次

owfi6suc  于 2022-11-26  发布在  其他
关注(0)|答案(2)|浏览(275)

所以在实现一个新特性之前,我正在做一些单元测试,我运行我的测试,它失败了,OverflowException : Maximum retries of 10000 reached without finding a unique value。这是我正在运行的测试。

public function test_job_factory()
    {
        $client = Client::factory()->create();
        $accountHandler = AccountHandler::factory()->create();
        $user = User::factory()->create();

        $this->post('/login', [
            'email' => $user->email,
            'password' => 'password',
        ]);

        $user->givePermissionTo( 'manage jobs' );
        $clientContact = ClientContact::factory()->create();
        $job = Job::factory()->create();

        $this->assertTrue($job->id > 0);
    }

错误似乎是在创建作业本身时发生的。上面的测试测试了其他工厂,并且正在工作。
下面是JobFactory.php文件:

<?php

namespace Database\Factories;

use App\Models\AccountHandler;
use App\Models\Client;
use App\Models\ClientContact;
use App\Models\Job;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Job>
 */
class JobFactory extends Factory
{
    protected $model = Job::class;

    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition()
    {
        return [
            'title'              => $this->faker->company(),
            'is_active'          => 1,
            'is_draft'           => 0,
            'client_id'          => $this->faker->unique()->numberBetween(1, Client::count()),
            'account_handler_id' => $this->faker->unique()->numberBetween(1, AccountHandler::count()),
            'eclipse_contact_id' => $this->faker->unique()->numberBetween(1, User::count()),
            'client_contact_id'  => $this->faker->unique()->numberBetween(1, ClientContact::count()),
            'description'        => $this->faker->paragraphs(1),
        ];
    }
}

和迁移(create_jobs_table. php):

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('jobs', function (Blueprint $table) {
            $table->id('number');
            $table->boolean( 'is_active' )->default(true);
            $table->boolean( 'is_complete' )->default(true);
            $table->string('title', 64)->nullable();
            $table->timestamps();
            $table->foreignId('author')->nullable()->constrained()->references('id')->on('users');
            $table->text('description')->nullable();
            $table->foreignId('client_id')->nullable()->constrained()->references('id')->on('clients');
            $table->foreignId('client_contact_id')->nullable()->constrained()->references('id')->on('client_contacts');
            $table->foreignId('account_handler_id')->nullable()->constrained()->references('id')->on('account_handlers');
            $table->date('expiry_date')->nullable();
            $table->date('artwork_deadline')->nullable();
            $table->date('proof_deadline')->nullable();
            $table->integer('redirect')->nullable();
            $table->boolean( 'is_draft' )->default(true);
            $table->foreignId('eclipse_contact_id')->nullable()->constrained()->references('id')->on('users');
            $table->foreignId('subscription_id')->nullable()->constrained()->references('id')->on('subscriptions');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('jobs');
    }
};

我已经添加了创建一个作业所需的最小数据,所以不知道我错过了什么。
谢谢

***EDIT***我被要求给予一个链接,我在那里发现了使用unique和numberBetween的坏习惯,这里是一个示例Laravel factory error "Maximum retries of 10000 reached without finding a unique value" when I use unique Faker method,这不会像你期望的那样工作!

mspsb9vt

mspsb9vt1#

我建议您使用文档方法来解决此问题。https://laravel.com/docs/9.x/database-testing#factory-relationships
查看您的迁移表,很有可能您的工厂将无法工作,因为您在SQL级别上指示关系,这基本上将迫使您在相关表中具有记录,否则SQL将向您抛出错误。

cedebl8k

cedebl8k2#

问题是,当您尝试获取1到5(包括)之间的5个值时,您只能获取4个。第5个数字永远不会通过unique()验证。
这是因为当您运行unique的第一个示例时,例如

$faker-〉唯一()-〉介于(1,20)之间的数字

然后在另一个工厂中运行它,laravel通常会扩展前一个示例(我猜),如果这有意义的话。

$faker-〉唯一(真)-〉介于(1,20)之间的数字

它再次从1到20开始搜索
这为我解决了问题。
所以在unique()示例中总是传递true

相关问题