Laravel 8 — тестовый набор не запускает черты и вызывает ошибки нарушения целостности

У меня есть Trait, который я использую в нескольких моделях в своем приложении для установки UUID в модели:

<?php

namespace App\Traits;

use Illuminate\Support\Str;

trait UsesUuid
{
    protected static function bootUsesUuid()
    {
        static::creating(function ($model) {
            if (!$model->uuid) {
                $model->uuid = (string) Str::orderedUuid();
            }
        });
    }
}

Он отлично работает при обычном использовании приложения, но когда я пытаюсь написать тесты для создания модели с помощью post route и вывести response, я получаю ошибку Integrity constraint violation: 19 NOT NULL constraint failed: venues.uuid 500.

Пример теста, который я делаю:

public function testOwnerCanSuccessfullyCreateVenue()
{
    $amenity = Amenity::inRandomOrder()->pluck('id')->first();

    $response = $this->actingAs($this->createdUser('owner'))->post(route('venues.store'), [
        "name" => "create-name",
        "address_line_1" => "create-address_line_1",
        "address_line_2" => "create-address_line_2",
        "county" => "create-county",
        "postcode" => "create-postcode",
        "phone_number" => "create-phone_number",
        "notes" => "create-notes",
        "amenities" => [$amenity]
    ]);

    dd($response);
}

И столбец в моей миграции $table->uuid('uuid')->unique();

Все остальное работает блестяще, но я новичок в написании тестов и не знаю, как обойти эту проблему.

Причина, по которой я использовал Trait, заключалась в том, чтобы обойти выделение всех значений столбцов при сохранении в базе данных, поскольку я использую $request->validated() для заполнения модели:

$venue = Venue::create($request->validated()); 

И, очевидно, поскольку UUID здесь не устанавливается, это делается чертой, которая не прошла тест. Я могу пройти тест, и приложение все еще будет работать, если я удалю черту и сделаю:

$venue = Venue::create(
    $request->validated() + ['uuid' => Str::orderedUuid()]
); 

Это нормально, я могу жить с этим, но я хотел бы больше понять, почему Черта не срабатывает и как это обойти.

Изменить: просто чтобы добавить больше на основе приведенного ниже ответа, заполняемые поля определены правильно:

/**
 * The attributes that are mass assignable.
 *
 * @var array
 */
protected $fillable = [
    'uuid',
    'name',
    'address_line_1',
    'address_line_2',
    'county',
    'postcode',
    'phone_number',
    'notes',
];

person Andy Holmes    schedule 29.06.2021    source источник


Ответы (1)


Думаю проблема в модели. Venue модель должна использовать protected $fillable = ['uuid'];. Laravel по умолчанию защищает массовое назначение. Если вы предоставляете массив при создании модели, Laravel не разрешает этого. Вам нужно предоставить защищенный заполняемый массив, поэтому laravel может разблокировать только эти поля.

person Bapi    schedule 29.06.2021
comment
Если бы это было так, обходной путь не сработал бы, модель назначена правильно. - person Andy Holmes; 29.06.2021