2017-08-10 69 views
1

我有一个类,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。我已经尽我$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); 

我在做什么错在这里?

回答

0

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

现在,当clone $query被称为getPaginatedQuery(),嘲笑的Eloquent\Builder实例将能够拨打clone嘲笑Query\Builder实例。