seeInDatabase有时会由于1秒后的updated_at字段而失败

时间:2019-01-23 18:34:54

标签: laravel testing

我在Laravel 5.7中进行了一项测试,该测试通过了90%的时间。

有时会失败,这是因为created_at和updated_at之间还有一秒:

在数据库中:

"created_at" => "2019-01-23 18:27:36"
"updated_at" => "2019-01-23 18:27:37"

在本地设置$ setting中:

"created_at" => "2019-01-23 18:27:36"
"updated_at" => "2019-01-23 18:27:36"

我的测试:

/** @test */
    public function it_update_setting_for_championship()
    {
        $tournament = factory(Tournament::class)->create();
        $championship = factory(Championship::class)->create(['tournament_id' => $tournament->id, 'category_id' => 2]);
        $setting = factory(ChampionshipSettings::class)->create(['championship_id' => $championship->id]);

        $this->call('PUT', '/championships/' . $championship->id . '/settings/' . $setting->id, $setting->toArray());
        $this->assertResponseOk();
        $this->seeInDatabase('championship_settings', $setting->toArray());
    }

当然,我可以将$setting->toArray()放入一个变量中,然后将unset created_atupdated_at放入一个变量中,但是感觉不对...

为什么它不总是发生?

有人有更好的解决方案吗?

编辑:

ChampionshipSettingsFactory:

$factory->define(ChampionshipSettings::class, function (Faker\Generator $faker) use ($factory) {
    $tcs = Championship::all()->pluck('id')->toArray();

    return [
        'championship_id' => $faker->randomElement($tcs),
        'teamSize' => $faker->numberBetween(0, 6),
        'fightingAreas' => $faker->numberBetween(0, 4),
        'fightDuration' => "03:00",
        'hasPreliminary' => $faker->boolean(),
        'preliminaryWinner' => $faker->numberBetween(1, 2),
        'hasEncho' => $faker->boolean(),
        'enchoQty' => $faker->numberBetween(0, 4),
        'enchoDuration' => "01:00",
        'hasHantei' => $faker->boolean(),
        'cost' => $faker->numberBetween(0, 100),
        'preliminaryGroupSize' => $faker->numberBetween(0, 10),
        'preliminaryDuration' => $faker->numberBetween(0, 10),
        'seedQuantity' => $faker->numberBetween(0, 4),
        'hanteiLimit' => $faker->numberBetween(0, 10), // 1/2 Finals
        'enchoGoldPoint' => $faker->numberBetween(0, 10), // Step where Encho has no more time limit
        'limitByEntity' => $faker->numberBetween(0, 10),
    ];
});

1 个答案:

答案 0 :(得分:0)

您的问题是工厂的运作方式。您正在数据库中创建元素,然后在创建后覆盖值。

带有工厂的怪异的怪癖是,除非您在key => value对中使用函数作为值,否则它们将始终运行工厂代码,然后套用您被覆盖的代码。

将您的出厂设置更改为以下内容,以便您将函数用作ID:

$factory->define(ChampionshipSettings::class, function (Faker\Generator $faker) {
    return [
        'championship_id' => function() {
            // Setting the id to a function makes it so the below query doesn't run
            // If we do an overwrite when we are using this factory.
            return Championship::inRandomOrder()->first()->id
        },
        'teamSize' => $faker->numberBetween(0, 6),
        'fightingAreas' => $faker->numberBetween(0, 4),
        'fightDuration' => "03:00",
        'hasPreliminary' => $faker->boolean(),
        'preliminaryWinner' => $faker->numberBetween(1, 2),
        'hasEncho' => $faker->boolean(),
        'enchoQty' => $faker->numberBetween(0, 4),
        'enchoDuration' => "01:00",
        'hasHantei' => $faker->boolean(),
        'cost' => $faker->numberBetween(0, 100),
        'preliminaryGroupSize' => $faker->numberBetween(0, 10),
        'preliminaryDuration' => $faker->numberBetween(0, 10),
        'seedQuantity' => $faker->numberBetween(0, 4),
        'hanteiLimit' => $faker->numberBetween(0, 10), // 1/2 Finals
        'enchoGoldPoint' => $faker->numberBetween(0, 10), // Step where Encho has no more time limit
        'limitByEntity' => $faker->numberBetween(0, 10),
    ];
});

到目前为止,当您运行时:

$setting = factory(ChampionshipSettings::class)->create([
    'championship_id' => $championship->id
]);

即使您如上所述覆盖冠军ID,您也将不再运行查询以查找数据库来查找冠军ID。

此方法在https://laravel.com/docs/5.7/database-testing#relationships

的文档中提到了(几乎没有为什么)。

让我知道问题是否仍然存在。