Странное поведение с моделями и phpunit в laravel - Попытка получить свойство 'id' не-объекта - PullRequest
0 голосов
/ 20 ноября 2018

У меня очень странное поведение с PHPUnit в laravel.У меня есть тест invoices_are_split_between_extensions, который создает несколько расписаний с записями и контракт, в котором есть специальное условие, которое необходимо проверить.

Я собрал все необходимые функции в одну функцию, выполняющую тест в качестве примера.

/** @test */
public function invoices_are_split_between_extensions()
{
    $user = $this->user();
    $contract = factory(Contract::class)->states('complete')->create([
        'user_id' => $user->id
    ]);
    $extension = factory(ContractExtension::class)->create([
        'contract_id' => $contract->id,
        'start' => '2018-01-01',
        'end' => '2018-01-15',
        'sp' => '50',
        'pp' => '40',
    ]);
    $extension2 = factory(ContractExtension::class)->create([
        'contract_id' => $contract->id,
        'start' => '2018-01-16',
        'end' => '2018-01-31',
        'sp' => '50',
        'pp' => '40',
    ]);
    $timesheet = factory(Timesheet::class)->create([
        'user_id' => $user->id,
        'customer_id' => $contract->customer_id,
        'contract_id' => $contract->id,
        'extension_id' => $extension->id,
        'total' => 16,
        'date' => '2018-01-01',
    ]);
    $entry = factory(TimesheetEntry::class)->create([
        'date' => '2018-01-14',
        'value' => 8,
        'user_id' => $user->id,
        'tariff_id' => 1,
        'contract_id' => $contract->id,
        'customer_id' => $contract->customer_id,
        'extension_id' => $extension->id,
        'timesheet_id' => $timesheet->id,
        'invoiced' => false,
    ]);
    $entry1 = factory(TimesheetEntry::class)->create([
        'date' => '2018-01-15',
        'value' => 8,
        'user_id' => $user->id,
        'tariff_id' => 1,
        'contract_id' => $contract->id,
        'customer_id' => $contract->customer_id,
        'extension_id' => $extension->id,
        'timesheet_id' => $timesheet->id,
        'invoiced' => false,
    ]);
    $entry2 = factory(TimesheetEntry::class)->create([
        'date' => '2018-01-16',
        'value' => 4,
        'user_id' => $user->id,
        'tariff_id' => 1,
        'contract_id' => $contract->id,
        'customer_id' => $contract->customer_id,
        'extension_id' => $extension2->id,
        'timesheet_id' => $timesheet->id,
        'invoiced' => false,
    ]);

    $invoices = Invoice::fromTimesheet($timesheet);

    $this->assertCount(2, $invoices);
    $this->assertEquals(800, $invoices[0]->total);
    $this->assertEquals(200, $invoices[1]->total);
    $this->assertEquals($extension->id, $invoices[0]->extension_id);
    $this->assertEquals($extension2->id, $invoices[1]->extension_id);
}

Этот тест выдает ошибку ErrorException: Trying to get property 'id' of non-object

1) Tests\Feature\InvoiceTest::invoices_are_split_between_extensions
ErrorException: Trying to get property 'id' of non-object

/home/ilyas/script/clockwork/contract-module/src/Models/Contract.php:435
/home/ilyas/script/clockwork/timesheet-module/src/Models/Timesheet.php:293
/home/ilyas/script/clockwork/app/src/vendor/laravel/framework/src/Illuminate/Support/Collection.php:1011
/home/ilyas/script/clockwork/app/src/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Collection.php:261
/home/ilyas/script/clockwork/timesheet-module/src/Models/Timesheet.php:303
/home/ilyas/script/clockwork/invoice-module/src/Models/Invoice.php:272
/home/ilyas/script/clockwork/app/src/tests/Feature/InvoiceTest.php:145

Когда я перехожу к строке 435 в Contract.php, я нахожу следующую строку.Где $tariff->id в соответствии с ошибкой, а не объектом.

$override = $this->tariffs->where('id', $tariff->id)->first()->pivot->sp ?? null;

После быстрого dd() я обнаружил, что это объект, экземпляр Tariff, называемый Tariff::findOrFail($key);, возвращаетдопустимый красноречивый объект.Теперь начинается самое интересное.Если я получу идентификатор как $tariff['id'], это сработает.Если я пытаюсь что-то вроде $tariff->toArray(), я получаю ошибку Error: Call to a member function toArray() on null.

$tariff = $tariff->toArray();
$override = $this->tariffs->where('id', $tariff['id'])->first()->pivot->sp ?? null;

Если я dd() $ тарифицирую до toArray(), я получаю коллекцию Eloquent.Если я dd() после $override, я получаю ту же коллекцию, что и массив.Если я удаляю dd(), ошибка появляется снова ... Это сводит меня с ума на несколько часов.

Я легко могу исправить эту функцию с помощью tariff['id'], но я узнал, что может быть причиной этой проблемы.

...