在 Laravel 中模拟具有关系的模型

Posted

技术标签:

【中文标题】在 Laravel 中模拟具有关系的模型【英文标题】:Mocking models with a relationship in Laravel 【发布时间】:2013-12-20 02:42:44 【问题描述】:

我正在尝试创建 CustomObject 的嘲弄,然后使用与以下相同的东西将 OtherObject 的检索链接到它上面

$this->CustomObject->with('OtherObject')->get();

我似乎无法弄清楚如何在最后模拟这个->get()。我在我的构造方法['Eloquent', 'OtherObject', 'CustomObject'] 中模拟了这两个模型。如果我删除 ->get() 一切运行顺利并且我的测试通过(除了 php 错误,视图将给我,但如果测试正常工作,这些都无关紧要)。

我目前拥有的是这样的:

$this->mock->shouldReceive('with')->once()->with('OtherObject');
$this->app->instance('CustomObject', $this->mock);

我应该怎么做才能模拟这个?

编辑:我专门尝试了->andReturn($this->mock),它只告诉我在模拟对象上没有 get 方法。

【问题讨论】:

【参考方案1】:

您必须返回一个模拟实例才能进行下一个链接调用 (->get()) 才能工作

$this->mock
     ->shouldReceive('with')
     ->once()
     ->with('OtherObject')
     ->andReturn($this->mock);

【讨论】:

我已经专门尝试过了,它仍然说我不能使用公共成员获取非对象。 我不记得我的问题到底是什么,但你的方法肯定是正确的。【参考方案2】:

您可以使用Mockery::self() 定义带有参数的链式期望。

$this->mock->shouldReceive('with')
    ->once()->with('OtherObject')
    ->andReturn(m::self())->getMock()
    ->shouldReceive('get')->once()
    ->andReturn($arrayOfMocks);

在某些情况下,您可能需要将其拆分为两个模拟:

$mockQuery = m::mock();
$this->mock->shouldReceive('with')
    ->once()->with('OtherObject')
    ->andReturn($mockQuery);
$mockQuery->shouldReceive('get')->once()
    ->andReturn($arrayOfMocks);

【讨论】:

【参考方案3】:

看起来我有它。似乎之前的答案和我的尝试非常接近。使用这些的最大问题是在返回对象上调用了一个方法。如果这不是最好的方法,我希望有人能纠正我。

$other_object = Mockery::mock('OtherObject');
$other_object->shouldReceive('get')->once()->andReturn(new OtherObject);

$this->mock->shouldReceive('with')
           ->once()
           ->with('OtherObject')
           ->andReturn($other_object);

$this->app->instance('CustomObject', $this->mock);

并从构造方法中删除“OtherObject”。

【讨论】:

以上是关于在 Laravel 中模拟具有关系的模型的主要内容,如果未能解决你的问题,请参考以下文章

laraver框架学习------工厂模型填充测试数据

laravel 4 嘲弄模拟模型关系

Laravel 获取所有具有关系的模型

PhpUnit - 用关系模拟 laravel 模型

Laravel - 我有一个具有不同角色的用户模型。如何在具有特定角色的用户之间建立关系? [关闭]

如何通过多对多关系获取与同一张表相关的行 - Laravel