assertwell/phpunit-global-state

Protect against Runkit (re-)definitions happening before fixtures run

Closed this issue · 0 comments

Ran into this on project that implements this library:

Imagine we have a test class that looks like this:

<?php

namespace Tests;

use AssertWell\PHPUnitGlobalState\Constants;
use PHPUnit\Framework\TestCase;

class MyTest extends TestCase
{
    use Constants;

    /**
     * @before
     */
    protected function defineInitialConstants(): void
    {
        $this->setConstant('SOME_CONSTANT', 'some value');
    }
}

In some versions of PHPUnit (in my experience, 5.x for PHP 5.6), MyTest::defineInitialConstants() will be executed before the Constants::resetConstants() fixture, meaning the following steps happen in order:

  1. The SOME_CONSTANT constant gets defined, and its name tracked in $_constants (implicitly creating the array structure)
  2. Constants::resetConstants() executes, overwriting the $_constants property with a properly-formatted array
  3. The test method executes, with SOME_CONSTANT defined as expected
  4. The Constants::restoreConstants() fixture runs, but sees no constants in $_constants to restore and thus does nothing

If a fixture attempts to define a constant (or, once #11 and #12 are completed, a function/method), an error should be thrown if this occurs before the @before fixture has run.