The code will explain everything:
<?php class ATest extends PHPUnit_Framework_TestCase { public function testDestructorOnOriginalClass() { $a = new A(); // It unset($a); // works echo " great!"; // great! $this->expectOutputString('It works great!'); } public function testDestructorOnMockedClass() { $a = $this->getMock('A', array('someNonExistingMethod')); // It unset($a); // works echo " great!"; // great! $this->expectOutputString('It works great!'); } } class A { public function __construct() { echo "It"; } public function __destruct() { echo " works"; } }
and conclusion:
# phpunit ATest.php PHPUnit 3.7.13 by Sebastian Bergmann. .F Time: 0 seconds, Memory: 3.50Mb There was 1 failure: 1) ATest::testDestructorOnMockedClass Failed asserting that two strings are equal. --- Expected +++ Actual @@ @@ -'It works great!' +'It great! works' FAILURES! Tests: 2, Assertions: 2, Failures: 1.
As you can see in the second test, it prints works in the wrong order, perhaps because phpunit keeps a link to mock somewhere and __destruct() is called at the end of the test ... Ok I already checked getMock() , and in fact it stores a reference to a mocked object ( $this->mockObjects[] = $mockObject; ), which effectively blocks the object from destruction and therefore __destructor() never called.
public function getMock($originalClassName, $methods = array(), array $arguments = array(), $mockClassName = '', $callOriginalConstructor = TRUE, $callOriginalClone = TRUE, $callAutoload = TRUE, $cloneArguments = FALSE) { $mockObject = PHPUnit_Framework_MockObject_Generator::getMock( $originalClassName, $methods, $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $cloneArguments ); $this->mockObjects[] = $mockObject; return $mockObject; }
So the question is, is there a way to prevent this? Ignoring __destruct() when it should be called, I consider a bad constraint.