测试克隆模拟参数的方法
Posted
技术标签:
【中文标题】测试克隆模拟参数的方法【英文标题】:Testing a method that clones a mocked parameter 【发布时间】:2018-01-19 07:10:08 【问题描述】:我有一个类 getPaginatedQuery
,它的第一步会立即克隆它的一个参数:
public function getPaginatedQuery(Builder $query, $limit = null, $offset = null)
$constrainedQuery = clone $query;
...
Builder
对象的克隆是通过其__clone
魔术方法完成的。
我正在尝试通过为$query
传递一个模拟的Builder
实例来对该方法进行单元测试:
$query = m::mock('Illuminate\Database\Eloquent\Builder');
$relation->getPaginatedQuery($query, 2, 1);
我的测试因致命错误而失败:__clone method called on non-object
。我尝试在我的 $query
对象上定义对 __clone
的期望,但我得到了同样的错误:
$query = m::mock('Illuminate\Database\Eloquent\Builder');
$clonedQuery = m::mock('Illuminate\Database\Eloquent\Builder');
$query->shouldReceive('__clone')->andReturn($clonedQuery);
$relation->getPaginatedQuery($query, 2, 1);
我在这里做错了什么?
【问题讨论】:
【参考方案1】:Eloquent\Builder
实际上包含(作为成员)Query\Builder
的一个实例,其神奇的__clone
方法在这个底层Query\Builder
对象上调用clone
:
/**
* Force a clone of the underlying query builder when cloning.
*
* @return void
*/
public function __clone()
$this->query = clone $this->query;
由于您在模拟 Eloquent\Builder
,它实际上并没有底层的 $this->query
成员,因为它将在 Eloquent\Builder
的构造函数中设置,而该构造函数永远不会在完全模拟的对象中被调用。
要解决这个问题,您需要创建一个 Eloquent\Builder
的部分模拟,并使用 Query\Builder
的模拟实例告诉 run its real constructor:
$baseQuery = m::mock('Illuminate\Database\Query\Builder');
$query = m::mock('Illuminate\Database\Eloquent\Builder', [$baseQuery])->makePartial();
$relation->getPaginatedQuery($query, 2, 1);
现在,当在 getPaginatedQuery()
中调用 clone $query
时,模拟的 Eloquent\Builder
实例将能够在 其 模拟的 Query\Builder
实例上调用 clone
。
【讨论】:
以上是关于测试克隆模拟参数的方法的主要内容,如果未能解决你的问题,请参考以下文章