PhpUnit - 用关系模拟 laravel 模型
Posted
技术标签:
【中文标题】PhpUnit - 用关系模拟 laravel 模型【英文标题】:PhpUnit - mocking laravel model with relations 【发布时间】:2018-05-25 00:56:53 【问题描述】:我正在尝试模拟(仅作为示例)$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() 吗?不知道怎么做
【问题讨论】:
该错误似乎与您的代码中的任何内容都不对应。 【参考方案1】:可以通过使用具有有效类名的别名前缀来解决此错误。像下面这样:
$m = m::mock('alias:App\Models\User');
更多信息可以查看官方文档http://docs.mockery.io/en/latest/reference/creating_test_doubles.html#aliasing
【讨论】:
【参考方案2】:您也可以这样使用。
use App\Models\User;
class SomeClass
public function getActivePost(User $user): Collection
$user->load('posts');
return $user->posts;
首先您需要模拟帖子,然后将其添加到 Collection(不要忘记在顶部 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);
【讨论】:
【参考方案3】:我也不会在这里使用模拟。完全没有必要。所以我写的单元测试是:
创建用户。 创建一些用户创作的帖子。 对用户和帖子执行断言。所以代码在我的测试中会是这样的:
$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);
【讨论】:
【参考方案4】:如果你想测试这种关系,你可以:
/** @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);
【讨论】:
这不是问的,实际上是相反的:这里你实际上是通过关系创建一个Post
实例,而问题要求嘲笑关系,即:没有真正的@ 987654323@ 实例,但 $user->posts()->get()
表现得好像它是一个。以上是关于PhpUnit - 用关系模拟 laravel 模型的主要内容,如果未能解决你的问题,请参考以下文章
在 Laravel 中使用 Mockery/phpUnit 时出错
如何用 phpunit 模拟 Laravel Eloquent 模型?