PhpUnit - 嘲笑laravel模型与关系

时间:2017-12-11 13:26:14

标签: laravel unit-testing eloquent phpunit

我正在尝试模拟(仅限示例)$ user-> posts() - > get()。

示例服务:

use App\Models\User;

class SomeClass{
    public function getActivePost(User $user): Collection
    {
        return $user->posts()->get();
    }
}

和我的模特: 和型号:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use \App\Models\Post;

class User extends Model
{
    public function posts() : HasMany
    {
        return $this->hasMany(Post::class);
    }
}

这不起作用:

$this->user = Mockery::mock(User::class);
$this->user
    ->shouldReceive('wallets->get')
    ->andReturn('test output');

错误: TypeError:Mockery_2_App_Models_User :: posts()的返回值必须是Illuminate \ Database \ Eloquent \ Relations \ HasMany的实例,返回Mockery_4__demeter_posts的实例

没有返回类型提示(在post()方法上)一切正常。我必须修改andReturn()吗? idk如何

4 个答案:

答案 0 :(得分:1)

如果你想测试你可以的关系:

 /** @test */
function user_has_many_posts()
{
    $user = factory(User::class)->create();
    $post= factory(Post::class)->create(['user_id' => $user->id]);

    //Check if database has the post..
    $this->assertDatabaseHas('posts', [
        'id' => $post->id,
        'user_id' => $user->id,
    ]);
    //Check if relationship returns collection..
    $this->assertInstanceOf('\Illuminate\Database\Eloquent\Collection', $user->posts);

}

答案 1 :(得分:0)

我也不会在这里使用嘲笑。绝对没有必要。所以我写的单元测试将是:

  • 创建用户。
  • 创建一些由用户创作的帖子。
  • 对用户&执行断言讯息。

所以代码在我的测试中会是这样的:

$user = factory(User::class)->create();
$posts = factory(Post::class, 5)->create(['user_id' => $user->id]);

$this->assertNotEmpty($user->id);
$this->assertNotEmpty($posts);

$this->assertEquals(5, $posts->fresh()->count());
$this->assertEquals($user->id, $post->fresh()->first()->user_id);

答案 2 :(得分:0)

使用带有效类名的别名前缀可以解决此错误。如下所示:

$m = m::mock('alias:App\Models\User');

更多信息可在官方文档http://docs.mockery.io/en/latest/reference/creating_test_doubles.html#aliasing

中找到

答案 3 :(得分:0)

或者,您可以像这样使用。

use App\Models\User;

class SomeClass{
    public function getActivePost(User $user): Collection
    {
        $user->load('posts');
        return $user->posts;
    }
}

首先,您需要模拟帖子,然后将其添加到收藏夹中(不要忘了在顶部use放置它)。然后,当您调用posts属性时,其属性将被嘲笑$posts。在这种情况下,它不会引发有关返回类型的错误。

use Illuminate\Database\Eloquent\Collection;


$post = $this->mock(Post::class)->makePartial();
$posts = new Collection([$post]);

$this->user = Mockery::mock(User::class);
$this->user
    ->shouldReceive('getAttribute')
    ->with('posts');
    ->andReturn($posts);