2016-04-03 83 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)。 –