PHPUnit cannot find classes via namespace autoloader
We have the following simplified folder structure:
phpunit.xml autoloading.php index.php /models /user user.php ... /settings preferences.php ... /tests test.php
These are the contents of the respective 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 / preferences / 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 loading via namespace . Since the namespace follows the folder structure, everything is loaded automatically.
Now, we would like to configure some PHPUnit tests (via phpunit.phar, not composer) that 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, we get the following error:
Fatal error: Class 'models\user\User' not found in tests\test.php on line 7
We could of course add the following method to our test:
public function setup()
{
require_once '../models/user/user.php';
}
But then the following error will happen, etc .:
Fatal error: Class 'models\settings\Preferences' not found in models\user\user.php on line 11
Any idea what we should change to make autoloading work in tests? We've tried so many things, but it just won't work.
Thank!
source to share
We found a solution to this problem:
Instead of using our own autoloading.php file (see above), we now use psr-4 autoloading via composer . Our composer.json file looks like this:
{
"autoload": {
"psr-4": {
"models\\": "models/"
}
}
}
Once launched composer install
, a new folder is created vendor
containing autoload.php
. This file may be required in index.php as well as phpunit.xml ( <phpunit bootstrap="vendor/autoload.php">
).
With this autoload setting (using the same namespaces) everything works without issue.
source to share