因此,在实现新功能之前,我正在进行一些单元测试。我运行测试,但失败并出现 OverflowException :最大重试次数达到 10000 次,但未找到唯一值
这是我正在运行的测试。
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'); } };
那么出了什么问题,为什么会出现这个循环?我已经添加了创建作业所需的最少数据,因此不知道我错过了什么。
谢谢
*** 编辑 *** 我被要求提供一个链接,指向我发现使用 unique 和 numberBetween 的不好做法的地方,这里是一个示例 Laravel 工厂错误“最大重试次数达到 10000 次,但没有找到唯一值”,当我使用 unique Faker 方法时,这不会像你那样工作期待!
问题是当你尝试获取 1 到 5 之间的 5 个值时 (包括),你只能取4个。第5个数字永远不会超过
unique()
验证。这是因为,例如,当您运行 unique 的第一个实例时
然后在另一个工厂中运行它,laravel 通常会扩展前一个实例(我猜),如果这有意义的话。 但是当你像下面这样传递true时
它再次开始从 1 到 20 搜索
这解决了我的问题。
因此始终在
unique()
实例中传递 true我建议遵循文档方法来解决此问题。 https://laravel.com/docs/9.x/database-测试#工厂关系
看看你的迁移表,你的工厂很有可能无法工作,因为你在SQL级别上指示了关系,这基本上会迫使你在相关表中拥有记录,否则SQL会抛出错误..