2016-04-03 62 views
0

,我不能讓我的頭圍繞這一點:測試一對多關係Laravel,雄辯不工作

$fragment = factory(Fragment::class)->create(); 

$this->assertCount(0, $fragment->values); 

fragment->fetch(); // updates the 'values' by adding one Value object. 

var_dump($fragment->id); // i.e. 6 
var_dump(Fragment::first()->id); // 6 

var_dump($fragment->values->count()); // 0 
var_dump(Fragment::first()->values->count()); // 1 

$this->assertCount(1, $fragment->values); 

我用DatabaseTranscations,所以創建一個片段後,總有一個且只有一個。因此,$ fragment和Fragment :: first()是完全相同的實例。然而...價值關係是不同的。這怎麼可能呢?

請注意,這隻發生在測試過程中,當我通過我的控制器手動測試(並將值傳遞到刀片模板頁面)時,它工作得很好。我很困惑:S。

任何想法?

回答

1

關係屬性($fragment->values)只加載一次。當您添加或刪除關係中的項目時,它們不會保持最新狀態。他們不會每次都檢查數據庫以檢查更改。

您的第二行是$this->assertCount(0, $fragment->values);。在這裏訪問$fragment->values懶加載關係,並根據您的斷言證明,它是空的。

然後,您可以撥打$fragment->fetch(),其中您的評論表示它將一個Value對象添加到該片段。但是,您的關係屬性($fragment->values)已經從前面的語句中加載,因此它不會反映您添加到關係中的其他Value對象。

因此,即使在呼叫fetch()後,$fragment->values仍然是一個空的集合。但是Fragment::first()->values將包含新相關的Value,因爲它正在獲取Fragment的新實例,並且當它第一次加載values時,它將拾取相關的Value

當您需要重新加載關係時,可以使用load()方法。如果您在致電fetch()(或將其放入您的fetch()方法中,無論哪一個對您有意義)後添加此項,您的測試將正常工作。

$fragment = factory(Fragment::class)->create(); 

$this->assertCount(0, $fragment->values); 

$fragment->fetch(); // updates the 'values' by adding one Value object. 

var_dump($fragment->id); // i.e. 6 
var_dump(Fragment::first()->id); // 6 

var_dump($fragment->values->count()); // 0 

// reload the values relationship 
$fragment->load('values'); 

var_dump($fragment->values->count()); // 1 
var_dump(Fragment::first()->values->count()); // 1 

$this->assertCount(1, $fragment->values); 

你有另一種選擇是通過訪問關係方法而不是關係屬性使用關係查詢。如果你這樣做$fragment->values()->count()(注意:values(),而不是values),那麼每次都會觸發數據庫並始終返回當前計數。

+0

非常好,這工作得很好。奇怪的是,我閱讀文檔並沒有發現/理解上述行爲。當然有一個提到急切的加載(https://laravel.com/docs/5.2/eloquent-relationships#lazy-eager-loading)。 –