2015-07-03 20 views
6

Używam phpunit z kpiną (bez DB/fixtures), ale mam problem z kpiną z modelu.Yii2 ActiveRecord szyderczy z kpiną

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

Produkuje błąd:

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

Potem próbowałem:

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

Ale znowu, biegnę do:

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

Jakieś sugestie?

Odpowiedz

2

Wiem, że nie akceptujesz odpowiedzi na mecze, ale nie mogłem tego rozgryźć. Problemem, który próbowałem rozwiązać, było kpiny z niektórych metod w modelu, aby uniknąć tworzenia ukrytych urządzeń.

Więc skończyło się używając Proxy wdrożenie wzoru w kpina

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 
    ... 
} 

W tym przykładzie getPrice() metody z Product modelu zwraca Product cena od powiązanych tabelach. I wyśmiewamy to tutaj, abyśmy nie musieli wypełniać db wszystkimi powiązanymi modelami urządzeń. Mimo to, sam Product wciąż jest urządzeniem stałym.

Może nie najlepsze rozwiązanie, ale udało mi się zaoszczędzić trochę czasu procesora przy jednoczesnym zachowaniu rozdzielonych testów jednostkowych.

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

aktualizacji:

Ja również małą pomocnika do rozwiązania atrybut buforowania problemu

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

ten sposób wszystkie atrybuty i odpowiadające im wartości z oryginalnego modelu stać dostępne w wersji próbnej.

+0

Dzięki, wypróbuję! –

1

Czy lub Passive Partial Mock czego szukasz?

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

Powyższy przykład nie zwróci niczego, ponieważ identyfikator nie jest ustawiony, ale nie będzie powodował żadnych błędów.

+0

Myślę, że to jest problem w pierwszej kolejności. To podejście tworzy nową instancję '' CustomerModel'', która nie jest trwała pod względem ActiveRecord. W tym samym czasie nie możesz kpić z id, ponieważ w jakiś sposób '' $ customer-> id = 123'' nie przydzieli wartości – paulus