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!

+3


source to share


1 answer


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.

+3


source







All Articles