使用Laravel 5和sqlite进行单元测试。我有一个简单的测试,其中User
创建了Post
。
/** @test */
public function it_should_increment_post_count_when_a_user_makes_a_post()
{
// Given
$u = User::first();
$count1 = $u->posts->count();
var_dump($count1);
// When
$p = new Post();
$p->title = 'My Title';
$p->content = 'This is the content';
$p->user_id = $u->id;
$p->save(); // This is definitely saving
$count2 = $u->posts->count();
var_dump($count2);
// Then
$this->assertEquals($count1+1, $count2);
}
结果如下:
root@7053bd7f558c:/var/www/laravel# phpunit
PHPUnit 5.5.7 by Sebastian Bergmann and contributors.
.....Fint(11)
int(11)
. 7 / 7 (100%)
Time: 1.98 seconds, Memory: 12.00MB
There was 1 failure:
1) BasicUserTest::it_should_increment_post_count_when_a_user_makes_a_post
Failed asserting that 11 matches expected 12.
/var/www/laravel/tests/BasicUserTest.php:96
FAILURES!
Tests: 7, Assertions: 11, Failures: 1.
当然可以保存到数据库中(如果我在没有use DatabaseTransactions;
的情况下运行它,它每次都会递增)。 $count1
是否以某种方式引用$u->posts->count()
?
编辑: 类似的变化产生了一个奇怪的属性:
/** @test */
public function it_should_increment_post_count_when_a_user_makes_a_post()
{
// Given
$p = new Post([
'title' => 'tha title',
'content' => 'tha content',
]);
$u_old = User::first();
var_dump($u_old->posts->count());
// When
$u_old->posts()->save($p);
// Then
$u_new = User::first();
$this->assertEquals($u_old->posts->count()+1, $u_new->posts->count());
}
这样可行,但如果我注释掉var_dump($u_old->posts->count());
行,则会失败。
答案 0 :(得分:3)
当你这样写:
$u->posts->count();
不是模型中缓存的count()
。这是posts
关系。您将所有用户的帖子作为Collection
(基本上是一个美化的数组),然后count
集合中的项目数量
如果您只需要帖子数量,则不加载完整集合。您只应在实际需要有关每个帖子的详细信息时加载该集合。
相反,这样做:
$u->posts()->count();
在帖子后注意()
。这意味着您实际上正在构建一个查询以选择发布的总数。这样:
答案 1 :(得分:2)
count
保持相同的值,因为该值存储在Eloquent模型中。
这是保留在记忆中的值。
因此,插入后,您需要发出新请求。
例如:
<?php DB::table('name')->count(); ?>
或者只是真正的计数:<?php $count2 = count($y->posts); ?>
(我不记得是否有重新加载计数器值的提示......)
答案 2 :(得分:2)
所选答案是正确的,但我想我会为另一个选项提供输入。它在插入后保存第二个查询。
插入后,您可以刷新User
模型上的关系数据。
// Get fresh data for posts relationship
$u = $u->fresh();
来自API docs:
从数据库重新加载新模型实例。