I'm using an ORM and the way I get an object of the record is using FooModel::find(1)
. FooModel
has a method I need to mock for testing. How can I do it? (Can't use the PHPUnit mock
because that would give me a mocked FooModel
that'll not correspond to the record with ID 1
.)
Example:
class FooModel
{
// ORM model that fetches record from the DB
public function thisNeedsToBeMocked()
{
// some code here that depends on external factors so should be part of unit tests
}
}
The way I get the record with ID 1
is:
$fooObject = FooModel::find(1);
I need to be able of mock the thisNeedsToBeMocked()
of $fooObject
that I have after I run the static
method find()
.
You have hit on a classic unit testing problem. The class name you are using to call statically is part of the global namespace. That means there is no point in which you can insert a mock. This is no magic you can do here, to solve this problem you will have to make some code changes.
There many ways to solve this and there are many fors and against each of them. I will give you a simple hacker solution. If you would like something different let me know and I will code up an example.
I will also assume that you can't change the ORM from being static class based.
Here is the hacker approach, which is a very bad way of doing things, so you know. Have a variable in your class that is the class name of the ORM class you need to use. This is PHP 5.3 code.
Like so:
<?php
class Bar {
public static $ormName = 'FooModel';
public static function doStuff()
{
$className = self::$ormName;
echo $className::find(1), "
";
}
}
Then in your PHPUnit test create a mock. Get it's class name, set that class name on your test subject. Now your test subject will call your mock.
There are so many ways to some this problem but some how you need a way to not use the class name directly.