2017-08-10 106 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實例。