I'm running phpunit with mockery (without DB/fixtures), but I have a trouble with mocking a model.
$customer = Mockery::mock(CustomerModel::class);
echo $customer->id;
Produces error:
BadMethodCallException: Method Mockery_1_models_Customer::hasAttribute() does not exist on this mock object
Then I tried:
$customer->shouldReceive('hasAttribute')->andReturn(true);
But again, I run in to:
Fatal error: Call to a member function getDb() on a non-object in ..\yiisoft\yii2\db\ActiveRecord.php on line 135
Any suggestions?
I know you are not accepting fixture answers, but I could not figure it out either. The problem I was trying to solve actually was mocking some methods in model so to avoid creating underlying fixtures.
So I ended up using Proxy
pattern implementation 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 this example getPrice()
method from Product
model returns Product
price from related tables. And we mock it here so that we won't have to populate db with all related models fixtures. Nevertheless Product
itself is still a fixture.
Maybe not the best solution, but managed to save me some CPU time while keeping unit tests decoupled.
Docs here http://docs.mockery.io/en/latest/reference/partial_mocks.html
update:
I also made a small helper to solve attribute 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;
}
This way all attributes and their corresponding values from original model become available in mock.
Is Traditional Partial Mock or Passive Partial Mock what you are looking for?
$customer = Mockery::mock(CustomerModel::className())->makePartial();
echo $customer->id;
The sample above would of course not return anything since id is not set, but wont throw any errors.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With