Note that there are some explanatory texts on larger screens.

plurals
  1. POWhy phpunit doesn't run __destruct() in mocked class and how to force it?
    primarykey
    data
    text
    <p>Code will explain everything:</p> <pre><code>&lt;?php class ATest extends PHPUnit_Framework_TestCase { public function testDestructorOnOriginalClass() { $a = new A(); // It unset($a); // works echo " great!"; // great! $this-&gt;expectOutputString('It works great!'); } public function testDestructorOnMockedClass() { $a = $this-&gt;getMock('A', array('someNonExistingMethod')); // It unset($a); // works echo " great!"; // great! $this-&gt;expectOutputString('It works great!'); } } class A { public function __construct() { echo "It"; } public function __destruct() { echo " works"; } } </code></pre> <p>and the output:</p> <pre><code># 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. </code></pre> <p>As you can see in the second test it prints <code>works</code> in wrong order, probably because phpunit stores reference to mock somewhere and <code>__destruct()</code> is called at the end of test... Ok I've already checked <code>getMock()</code> method and indeed it stores reference to mocked object (<code>$this-&gt;mockObjects[] = $mockObject;</code>) efficiently blocking object from being destructed and so <code>__destructor()</code> is never called.</p> <pre><code>/** * Returns a mock object for the specified class. * * @param string $originalClassName * @param array $methods * @param array $arguments * @param string $mockClassName * @param boolean $callOriginalConstructor * @param boolean $callOriginalClone * @param boolean $callAutoload * @param boolean $cloneArguments * @return PHPUnit_Framework_MockObject_MockObject * @throws PHPUnit_Framework_Exception * @since Method available since Release 3.0.0 */ 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-&gt;mockObjects[] = $mockObject; return $mockObject; } </code></pre> <p>So the question is - is there a way to prevent this? Ignoring <code>__destruct()</code> when it should be called is I think bad limitation.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload