我在laravel中使用PHPUnit有一些非常奇怪的行为。我有一个测试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
当我转到Contract.php
中的第435行时,发现以下行。根据错误,$tariff->id
不是对象。
$override = $this->tariffs->where('id', $tariff->id)->first()->pivot->sp ?? null;
在快速dd()
之后,我发现这是一个对象,名为Tariff
的{{1}}实例返回有效的雄辩对象。
现在,有趣的部分开始了。如果我得到Tariff::findOrFail($key);
这样的ID,它就可以工作。如果我尝试使用类似$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()
之后dd()
,我将得到与数组相同的集合。如果我移除$override
,该错误会再次出现...这使我疯狂了几个小时。
我可以使用dd()
轻松地修复该功能,但是我知道是什么导致了此问题。