Adding it in the bootstrap file doesn't work - why?
Is it because sometimes the function baz
is (A) correctly created by the system and sometimes (B) you need to mock it? Or (C) do you always need to mock it?
- Case A: Why is the code creating a vital function sporadically on the fly?
- Case B: A function can only be registrered once, and never unregistered or overwritten. Therefore, you either go with the mock or you don't. No mixing is allowed.
- Case C: If you always need to mock it, and you add it to the bootstrap file, it will be defined. Regarding what you've tried, either your bootstrap file for phpunit isn't loaded correctly or you misspelled the function's name.
I'm sure you've correctly configured your phpunit bootstrapping, but for good measure, does it look anything like the following:
/tests/phpunit.xml
:
<phpunit
bootstrap="phpunit.bootstrap.php"
</phpunit>
/tests/phpunit.bootstrap.php
:
<?php
require(__DIR__ . "/../bootstrap.php"); // Application startup logic; this is where the function "baz" gets defined, if it exists
if (function_exists('foo') && ! function_exists('baz')) {
/**
* Baz function
*
* @param integer $n
* @return integer
*/
function baz($n)
{
return foo() + $n;
}
}
Don't create the function baz
on the fly in your tests, e.g. in a setUp
function.
Test suites in phpunit use the same bootstrapper. Therefore, if you need to test cases where function baz
is defined and other cases where it is not defined (and you need to mock it), you need to split up the tests
folder, e.g. in two different folders, each with their phpunit.xml
and phpunit.bootstrap.php
files. E.g. /tests/with-baz
and /tests/mock-baz
. From these two folders, run the tests separately. Just create symlinks to the phpunit
in each subfolder (e.g. from /test/with-baz
create ln -s ../../vendor/bin/phpunit
if composer is in the root) to ensure you run the same version of phpunit in both scenarios.
The ultimate solution is, of course, to figure out where the baz
function is being defined and manually include the culprit script file, if at all possible, to ensure the correct logic is being applied.
Alternative
Use phpunit's @runInSeparateProcess
annotation and define the function as needed.
<?php
class SomeTest extends \PHPUnit_Framework_TestCase
{
/**
* @runInSeparateProcess
*/
public function testOne()
{
if (false === function_exists('baz')) {
function baz() {
return 42;
}
}
$this->assertSame(42, baz());
}
public function testTwo()
{
$this->assertFalse(function_exists('baz'));
}
}