Ιs there a way to test a function containing static variables using PHPUnit?
For example,
class MyClass {
public function my_method() {
static $already_invoked = false;
if ($already_invoked) {
return;
}
echo 'Hello world';
$already_invoked = true;
}
}
my_method()
will print Hello world
exactly one time, no matter how many times it's called.
$instance = new MyClass();
$instance->my_method();
$instance->my_method();
outputs:
Hello world
Having just one test
<?php
class MyMethodTest extends \PHPUnit\Framework\TestCase {
public function test_should_print_hello_world_exactly_one_time() {
$instance = new MyClass();
$instance->my_method();
$instance->my_method();
$this->expectOutputString('Hello world');
}
}
passes:
MyMethod
✔ Should print hello world exactly one time
However, adding another test
<?php
class MyMethodTest extends \PHPUnit\Framework\TestCase {
public function test_should_print_hello_world() {
(new MyClass())->my_method();
$this->expectOutputString('Hello world');
}
public function test_should_print_hello_world_exactly_one_time() {
$instance = new MyClass();
$instance->my_method();
$instance->my_method();
$this->expectOutputString('Hello world');
}
}
causes the previously passing test to fail, because of the static
variable:
MyMethod
✔ Should print hello world
✘ Should print hello world exactly one time
│
│ Failed asserting that two strings are equal.
│ --- Expected
│ +++ Actual
│ @@ @@
│ -'Hello world'
│ +''
│
Now, I know I could use a static property instead:
class MyClass {
private static bool $already_invoked = false;
public function my_method() {
if (self::$already_invoked) {
return;
}
echo 'Hello world';
self::$already_invoked = true;
}
}
That way, I could use a reflection property to reset its value immediately after each test, like this:
class MyMethodTest extends \PHPUnit\Framework\TestCase {
// ...
public function tearDown() {
$ref = new ReflectionProperty('MyClass', 'already_invoked');
$ref->setAccessible(true);
$ref->setValue(null, false);
}
}
And then, both tests pass:
MyMethod
✔ Should print hello world
✔ Should print hello world exactly one time
In my case, though, I'm dealing with legacy code and I'd like to write some unit tests before refactoring it.
I've also tried to run each test in isolation (although that's not ideal since it'd probably end up being considerably slower) using the @runInSeparateProcess
method annotation, but that seems to be failing because the process isolation feature requires serialization:
PHP Fatal error: Uncaught Exception: Serialization of 'ReflectionClass' is not allowed in phar:///usr/local/bin/phpunit/phpunit/Util/GlobalState.php:151
Is there a way to test a function containing static
variables?