2015-07-03 13 views
6

Sto eseguendo phpunit con mockery (senza DB/fixtures), ma ho un problema con il modello di derisione.Yii2 ActiveRecord che deride con Mockery

$customer = Mockery::mock(CustomerModel::class); 
echo $customer->id; 

Produce errore:

BadMethodCallException: Method Mockery_1_models_Customer::hasAttribute() does not exist on this mock object

Poi ho provato:

$customer->shouldReceive('hasAttribute')->andReturn(true); 

Ma ancora una volta, corro a:

Fatal error: Call to a member function getDb() on a non-object in ..\yiisoft\yii2\db\ActiveRecord.php on line 135

Qualche suggerimento?

risposta

2

So che non accetti le risposte alle fixture, ma non sono nemmeno riuscito a capirlo. Il problema che stavo cercando di risolvere in realtà stava prendendo in giro alcuni metodi nel modello in modo da evitare di creare fixture sottostanti.

Così ho finito per usare Proxy implementazione modello in Mockery

private $_product; 
public function testMe() 
{ 
    // Here we use fixtured instance of Product model to build a Proxy 
    $this->_product = \Mockery::mock($this->product('product1')); 
    // somehow model attributes are inaccessible via proxy, but we can set them directly as a Proxy property 
    $this->_product->id = 1; 
    $this->_product->shouldReceive('getPrice')->andReturn(1000); 
    // assertions below 
    ... 
} 

In questo esempio getPrice() metodo dal Product modello ritorna Product prezzo da tabelle correlate. E lo prendiamo in giro qui per non dover popolare db con tutti i modelli correlati. Tuttavia, lo stesso Product è ancora un appuntamento fisso.

Forse non è la soluzione migliore, ma è riuscito a risparmiarmi un po 'di tempo della CPU mantenendo i test delle unità disaccoppiati.

Documenti qui http://docs.mockery.io/en/latest/reference/partial_mocks.html

aggiornamento:

Ho anche fatto un piccolo helper per risolvere attributo proxying problema

/** 
* @param \yii\base\Model $model 
* @return \Mockery\MockInterface 
*/ 
private function setupMock($model) 
{ 
    $mock = \Mockery::mock($model); 
    foreach ($model->getAttributes() as $key => $value) { 
     $mock->$key = $value; 
    } 
    return $mock; 
} 

questo modo tutti gli attributi ei loro valori corrispondenti dal modello originale diventano disponibile in simulazione.

+0

Grazie, lo proverò! –

1

Traditional Partial Mock o Passive Partial Mock Cosa stai cercando?

L'esempio sopra ovviamente non restituirà nulla poiché l'ID non è impostato, ma non genera alcun errore.

+0

Penso che questo sia un problema in primo luogo. Questo approccio crea una nuova istanza di '' CustomerModel'' che non è persistente in termini di ActiveRecord. Allo stesso tempo non puoi prendere in giro id perché in qualche modo "$ customer-> id = 123'' non assegnerà alcun valore – paulus