问题
I am learning and exploring applications of PHPUnit with PHP 5.2.9 and have run into the globals issue. I have set $backupGlobals to FALSE, included the doc '@backupGlobals disabled' and this doesn't seem to affect the behaviour of PHPUnit's backing up of the globals. Is there something I'm missing? Do I need to alter PHPUnit's xml file? Create a bootstrap?
config.php:
$testString = 'Hello world!';
basicApp.php:
require ('D:\data\clients\security.ca\web_sites\QRASystems.com\wwwroot\__tests\BasicApp\config.php');
class BasicApp {
public $test;
public function __construct() {
global $testString;
$this->test = $testString;
}
public function getTest() {
return $this->test;
}
public function setTest($test){
$this->test = $test;
}
BasicAppTest.php:
require ('D:\data\clients\security.ca\web_sites\QRASystems.com\wwwroot\__tests\BasicApp\BasicApp.php');
class BasicAppTest extends PHPUnit_Framework_TestCase{
protected $testClass;
protected $backupGlobals = FALSE;
protected $backupGlobalsBlacklist = array('testString');
public function SetUp(){
$this->testClass = new BasicApp;
$this->testClass->bootstrap();
}
public function testGlobal(){
echo $this->testClass->getTest();
$this->assertNotNull($this->backupGlobals);
$this->assertFalse($this->backupGlobals);
$this->assertNotEmpty($this->testClass->test);
}
public function testMethods(){
$this->testClass->setTest('Goodbye World!');
echo $this->testClass->getTest();
$this->assertNotNull($this->backupGlobals);
$this->assertNotNull($this->testClass->test);
if (empty($this->testClass->test)) echo 'Method set failed!';
}
}
testGlobal() fails on $this->assertNotEmpty($this->testClass->test), indicating that $this->backupGlobals is set to FALSE and that globals are still being back up by PHPUnit.
EDIT: I got this working by making the following changes-
BasicAppTest.php:
protected $backupGlobals = FALSE; <- REMOVED
protected $backupGlobalsBlacklist = array('testString'); <- REMOVED
config.php:
global $testString; <- ADDED
$testString = 'Hello world!';
I am dumbfounded that this hasn't been covered before somewhere!
回答1:
In your test case you are defining a new $backupGlobals
property that PHPUnit won't see. Since the property is protected, you could set it to false
in the constructor, but PHPUnit uses its constructors to pass information on how to run the test method. Instead, create a phpunit.xml configuration file to set the backupGlobals
property to false
.
<phpunit backupGlobals="false">
<testsuites>
<testsuite name="Test">
<directory>.</directory>
</testsuite>
</testsuites>
</phpunit>
回答2:
In your edits and comments you've pointed out one workaround for the problem (explicitly declaring globals within the tested application). In onlab's comment to a PHPUnit issue he explains the behavior: when including a file in a function, PHP puts globals from the included files in the function's scope. PHPUnit loads files in a function, and though it tries to extract globals, it fails in the cases I've tried.
Unfortunately, I haven't been able to reproduce the problems of my legacy system in minimal test cases (and I had trouble understanding yours), and so I can't really confirm the explanation. But his suggested workaround helped me: supply a bootstrap file using the --bootstrap
option; in it, declare every global used by the tested parts of your application. This avoids the need to modify the application in order to test it. Here's onlab's example from GitHub:
phpunit --bootstrap bootstrap.php test-path
with bootstrap.php
:
global $my, $system, $globals, $here;
require_once("/path/to/my/system/bootstrap.php");
来源:https://stackoverflow.com/questions/9672178/phpunit-and-globals