2015-07-03 9 views
6

Ich betreibe phpunit mit Spott (ohne DB/Fixtures), aber ich habe ein Problem mit einem Modell spotten.Yii2 ActiveRecord Spott mit Mocker

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

Produziert Fehler:

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

Dann habe ich versucht:

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

Aber noch einmal, ich laufe in zu:

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

Irgendwelche Vorschläge?

Antwort

2

Ich weiß, dass Sie nicht Fixture-Antworten akzeptieren, aber ich konnte es auch nicht herausfinden. Das Problem, das ich zu lösen versuchte, war, einige Methoden im Modell zu verspotten, um zu vermeiden, dass darunterliegende Fixtures entstehen.

So landete ich Proxy Muster Implementierung 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 diesem Beispiel getPrice() Verfahren unter Verwendung von bis von Product Modell Product Preis von verknüpften Tabellen zurückgibt. Und wir verspotten es hier, damit wir db nicht mit allen zugehörigen Model-Fixtures füllen müssen. Dennoch ist Product selbst immer noch ein Fixpunkt.

Vielleicht nicht die beste Lösung, aber schaffte es, mir etwas CPU-Zeit zu sparen, während Komponententests entkoppelt bleiben.

Docs hier http://docs.mockery.io/en/latest/reference/partial_mocks.html

Update:

Ich habe auch ein kleines Helfer Attribut Proxying Problem

/** 
* @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; 
} 

diese Weise werden alle Attribute und ihre entsprechenden Werte aus Urmodell werden lösen verfügbar in Schein.

+0

Danke, ich werde es ausprobieren! –

1

Ist Traditional Partial Mock oder Passive Partial Mock nach was Sie suchen?

Das obige Beispiel würde natürlich nichts zurückgeben, da ID nicht gesetzt ist, aber keine Fehler werfen wird.

+0

Ich denke, das ist ein Problem an erster Stelle. Dieser Ansatz erstellt eine neue "CustomerModel" -Instanz, die in Bezug auf ActiveRecord nicht persistent ist. Zur gleichen Zeit können Sie die ID nicht vortäuschen, weil "$ customer-> id = 123'" irgendwie keinen Wert zuweisen wird – paulus