onoya.dev

CakePHP 2 Unit Test Mocking — Prevent assigning different Alias

Problem: Mock

If you have tried Mocking models, you might have encountered some problems especially for models that have Associations. One of those problem is, when you mock a model, it assigns an alias.

For example: model User will become Mock_User_b13d6ac9.

That will cause a lot of conflicts and one of them that I have encountered is, when I used the Containable behavior.

Solution

Let us check first the function for mocking, which in my case, I use TestCase::getMock(). These are the arguments that the function getMock accepts.

public function getMock($originalClassName, $methods = array(), array $arguments = array(), $mockClassName = '', $callOriginalConstructor = TRUE, $callOriginalClone = TRUE, $callAutoload = TRUE, $cloneArguments = FALSE) { ...

The parameters that is going to fix our problem will be the $arguments parameter.

If you’ll check the documentation of getMock function, the purpose of parameter $arguments is:

Parameters to pass to the original class’ constructor.

In this case, it will pass it to User model’s constructor. The User.php model extends the class Model.php. Now let us check the constructor of Model.php:

public function __construct($id = false, $table = null, $ds = null) { ...

The parameter that we will be needing is the $id parameter. Now let us check the documentation of parameter $id:

* If `$id` is an array it can be used to pass several options into the model. * * - `id`: The id to start the model on. * - `table`: The table to use for this model. * - `ds`: The connection name this model is connected to. * - `name`: The name of the model eg. Post. * - `alias`: The alias of the model, this is used for registering the instance in the `ClassRegistry`. * eg. `ParentThread`

As you can see, we can pass an array as a value to parameter $id. So what we will have to set is the name key. We are going to set the original alias in this key and that would fix our problem.

Eg.

$Mock = $this->getMock('User', ['getById'], ['id' => ['name' => 'User']]); $Mock->expects($this->any())->method('getById')->will($this->returnValue(['User' => []])); $this->User = $Mock;

Now if you try to run debug($this->User->alias), we could see that it’s now using User instead of generating an alias with a random key like Mock_User_b13d6ac9.