In my previous article I expanded a few ideas around test helpers and how to use setUp() and tearDown(). However, we still stayed in the realm of things built in to PHPUnit.
Here, I want to expand on a helper function I include in most of my main testing classes that allows for the concept of setUp(), but grants a bit more flexibility.
Why Write a Utility?
As I started developing more and more complex classes, I started running into limitations of setUp() and ended up putting a lot of set up code in each test. Specifically, one of the things I found myself doing a lot is calling getMockBuilder for the current class I was testing multiple times in tests to set it up differently.
Sure, for most of the cases, I could probably get away with mocking everything in the object and go from there, but there were other cases when I actually wanted to leave some of the methods alone. I needed a way to make the setMethods() call in the mock to be dynamic, and this is what I came up with.
Example Time!
Let’s look at our example setup from a few articles ago: the FooClass.
$fooclass = $this->getMockBuilder('FooClass')
->disableOriginalConstructor()
->setMethods(array("foo"))
->getMock();
In the call above, we are specifically setting “foo” as the function we want to mock in this case. Let’s say for example that there are other methods in the class that should always be mocked, but you want to pick and choose for the rest. For things like view functions, this makes really good sense, but the issue is that as soon as you specify something in setMethods(), the rest of the functions are not doubled.
To get around this, I set up a helper function that takes an array of methods as parameter and merges them with another array of known methods I want to mock.
class myTest extends PHPUnit_Framework_TestCase
{
protected $methods;
protected function setUp()
{
$this->methods = array("method1", "method2", "methodN");
}
protected function getCustomMock($methods = array())
{
$obj = $this->getMockBuilder("FooClass")
->disableOriginalConstructor()
->setMethods(array_merge($this->methods, $methods)
->getMock();
return $obj;
}
}
And to use it, let’s take our call above and convert it. This:
$fooclass = $this->getMockBuilder('FooClass')
->disableOriginalConstructor()
->setMethods(array("foo"))
->getMock();
Becomes this:
$fooclass = $this->getCustomMock(array("foo"));
Let’s walk through the impact of this. Originally, we were setting up our mock class in setUp(), but quickly found that not all cases were covered by one mocked object. This leads us to start creating custom mock calls inside of each test that is different, wasting cycles and calls because we are duplicating the work in both places. With the getCustomMock() function, we can put all of the functions that are shared inside of its setMethods() call, and pass them in, as needed, in all of our tests. We are still “calling the mock” in each test, but it reduces the footprint of the call and we can still customize it. It works out to be less code, but still maintains the customization needed for unique tests.