We have following, simplified folder structure:
phpunit.xml
autoloading.php
index.php
/models
/user
user.php
...
/settings
preferences.php
...
/tests
test.php
This is the content of the relevant files:
models/user/user.php
namespace models\user;
class User {
private $preferences;
public function __construct()
{
$this->preferences = new \models\settings\Preferences();
}
public function getPreferenceType()
{
return $this->preferences->getType();
}
}
models/settings/preferences.php
namespace models\settings;
class Preferences {
private $type;
public function __construct($type = 'default')
{
$this->type = $type;
}
public function getType()
{
return $this->type;
}
}
autoloading.php
spl_autoload_extensions('.php');
spl_autoload_register();
index.php
require_once 'autoloading.php';
$user = new \models\user\User();
echo $user->getPreferenceType();
When we run index.php, everything works fine with automatic autoloading via namespace. Since the namespace fits the folder structure, everything is loaded automagically.
We would now like to setup some PHPUnit tests (via phpunit.phar, not composer), that do also use the same autoloading mechanism:
phpunit.xml
<phpunit bootstrap="autoloading.php">
<testsuites>
<testsuite name="My Test Suite">
<file>tests/test.php</file>
</testsuite>
</testsuites>
</phpunit>
tests/test.php
class Test extends PHPUnit_Framework_TestCase
{
public function testAccess()
{
$user = new \models\user\User();
$this->assertEquals('default', $user->getPreferenceType());
}
}
When we run the test, however, we get following error:
Fatal error: Class 'models\user\User' not found in tests\test.php on line 7
We could of course add following method to our test:
public function setup()
{
require_once '../models/user/user.php';
}
But then following error would occur, etc.:
Fatal error: Class 'models\settings\Preferences' not found in models\user\user.php on line 11
Any idea what we have to change so that autoloading works within the tests as well? We have tried so many things, but it just won't work.
Thank you!
We have found a workaround to our problem:
Instead of using our own autoloading.php file (see above) we are now using psr-4 autoloading via composer. Our composer.json file looks like this:
{
"autoload": {
"psr-4": {
"models\\": "models/"
}
}
}
After having triggered composer install
a new folder vendor
is being created, containing autoload.php
. This file can be required within index.php as well as in phpunit.xml (<phpunit bootstrap="vendor/autoload.php">
).
With this autoloading setup (while still using the same namespaces) everything works seamlessly.