The Enterprise ' s saucer section crash landing

The Enterprise ' s saucer section crash landing (Photo credit: Wikipedia)

I’m very happy to announce the release of Mockery 0.9.0.

Mockery is a simple yet flexible PHP mock object framework for use in unit testing with PHPUnit, PHPSpec or any other testing framework. Its core goal is to offer a test double framework with a succint API capable of clearly defining all possible object operations and interactions using a human readable Domain Specific Language (DSL). Designed as a drop in alternative to PHPUnit’s phpunit-mock-objects library, Mockery is easy to integrate with PHPUnit and can operate alongside phpunit-mock-objects without the World ending.

According to the number crunching machines over at VersionEye, Mockery is the 7th most referenced Composer package for PHP with 1,051 packages currently referencing Mockery as a development dependency. That is a great achievement and I appreciate the efforts of everyone who has taken the time to send in issues and pull requests.

Thanks to the efforts of Dave Marshall (@davedevelopment), who has taken point on Mockery for most of 2013, the new release improves stability, performance and compatibility with HHVM. I was going to trawl through the commits to write a summary of changes, but Dave was kind enough to do that for me too so here are the highlights. The new 0.9.0 release is now available on and through the PEAR channel.

Mocking Protected Methods

Contentious point for purists, but Mockery now allows you to mock protected methods, but it’s specifically opt-in. Its main use case will be shorthand for making fake derivatives of abstract classes.


require "vendor/autoload.php";

abstract class Foo
 public function bar()
 $res = $this->doBar();
 return $res * 2;

 abstract protected function doBar();

$foo = Mockery::mock("Foo")->makePartial()


echo $foo->bar(); // 256

Generator Rewrite

The code generation has been completely rewritten, it’s a little cleaner and has more unit tests. This new generator is now wrapped with a caching layer by default. This means that Mockery wont generate a new mock class if it’s already generated a suitable class.


$fooMock1 = Mockery::mock("Foo"); // generates a mock class deriving from Foo
$fooMock2 = Mockery::mock("Foo"); // re-uses the same mock class

$partialFoo = Mockery::mock("Foo[bar]"); // can't reuse class, so generates new

This brings significant performance boosts on larger suites, particularly with memory consumption. It’s not all that important to some, but I like a fast feedback loop and it will definitely help some people running their suites on travis with xdebug for coverage.

laravel/framework with Mockery 0.8.0 and Zend PHP 5.5.6
Time: 3.9 seconds, Memory: 276.50Mb

laravel/framework with Mockery 0.9.0 and Zend PHP 5.5.6
Time: 1.61 seconds, Memory: 66.50Mb

laravel/framework with Mockery 0.8.0 and Zend PHP 5.5.6 w/xdebug
Time: 5.96 seconds, Memory: 334.25Mb

laravel/framework with Mockery 0.9.0 and Zend PHP 5.5.6 w/xdebug
Time: 3.38 seconds, Memory: 74.00Mb

laravel/framework with Mockery 0.8.0 and HHVM
Time: 42.91 seconds, Memory: 388.57Mb

laravel/framework with Mockery 0.9.0 and HHVM
Time: 2.19 seconds, Memory: 61.80Mb

As part of the rewrite, there are also interchangeable loaders. By default we use an EvalLoader, but you can configure the container to use the RequireLoader, which will dump the code to a file and then require it, allowing easier debugging etc.

HHVM Support

We’re almost entirely there, waiting for HHVM nightlies to incorporate one last fix and travis should go green, depending on what version of phpunit they use.

Named Mocks

One fall out of the caching support was that some people where depending on class names being different, in the cases where they wanted two different derivatives of the same abstract type. We added a static `namedMock` helper method to the deal with this.


$foo = Mockery::namedMock("MockFoo", "Foo");
echo get_class($foo); // MockFoo

Quick Defs Are Automatically `byDefault`

As the quick definitions can only ever be stubs, we set them to byDefault automatically, allowing quick defs to be used in setup etc, but overriden in specific tests.


$foo = Mockery::mock("Foo", array("bar" => 123));

echo $foo->bar(); // 456
Enhanced by Zemanta