测试克隆模拟参数的方法

时间:2017-08-10 21:36:37

标签: php unit-testing mocking clone mockery

我有一个类getPaginatedQuery,它的第一步是立即克隆其中一个参数:

public function getPaginatedQuery(Builder $query, $limit = null, $offset = null)
{
    $constrainedQuery = clone $query;
    ...
}

Builder对象的克隆是通过其__clone魔术方法完成的。

我试图通过为Builder传递一个模拟的$query实例来对此方法进行单元测试:

$query = m::mock('Illuminate\Database\Eloquent\Builder');
$relation->getPaginatedQuery($query, 2, 1);

我的测试因致命错误而失败:__clone method called on non-object。我已尝试在__clone对象上定义$query的期望,但我得到同样的错误:

$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 个答案:

答案 0 :(得分:0)

Eloquent\Builder实际上包含(作为成员)Query\Builder的实例,其魔法__clone方法在此基础clone对象上调用Query\Builder:< / p>

/**
 * 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);

现在,在clone $query中调用getPaginatedQuery()时,模拟的Eloquent\Builder实例将能够在上调用clone 模拟Query\Builder实例。