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 different 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(). Let us check the parameters of getMock.

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 docblock 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. And 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 docblock 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 do a debug($this->User->alias), we could see that it’s now using User instead generating an alias with a random key like Mock_User_b13d6ac9.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.