Question

I'm currently working on a Symfony2 project with Phpspec and I'm having problems to extend a Spec class described in a different namespace.

In my project, for instance, I'm having the following class described in spec/Acme/Model/Foo/FooSpec.php :

namespace spec\Acme\Model\Foo;

use PhpSpec\ObjectBehavior;
use Prophecy\Argument;

abstract class FooSpec extends ObjectBehavior{
    //some code here
}

And I have another class in spec/Acme/Model/Bar/BarSpec.php extending FooSpec :

namespace spec\Acme\Model\Bar;

use spec\Acme\Model\Foo\FooSpec;

class BarSpec extends FooSpec{
    //some code here
}

When I try to run phpspec, I have the following error :

PHP Fatal error: Class 'spec\Acme\Model\Foo\FooSpec' not found in /home/user/Projects/Acme/spec/Acme/Model/Bar/BarSpec.php on line 9

The only way I found to make it work was to add the following line in spec/Acme/Model/Bar/BarSpec.php:

include('./spec/Acme/Model/Foo/FooSpec.php');

I don't know why I have to include this specific file to make it run, especially when the other classes (like PhpSpec\ObjectBehavior) are correctly found.

Do you have any idea why is this happening?


Edit:

As suggested by @Phil and @Sheikh Heera in the comments, I tried to set up an autoload to register my spec namespace but it's not working neither. Here is what I tried so far :

require_once getcwd() . '/vendor/composer/ClassLoader.php';

$loader = new \Composer\Autoload\ClassLoader();

// register classes with namespaces
$loader->add('spec', getcwd().'/spec');

// activate the autoloader
$loader->register();

I also tried to modify the file vendor/composer/autoload_namespaces.php to add this :

return array(
    //some code here

    'spec' => array(getcwd() . '/spec'),
    //some more code

);

But still the same error. I also tried with 'spec' => array(getcwd()) or $loader->add('spec', getcwd()); just to see what will happen and this time I get a Cannot redeclare class on another spec class.


My php version is PHP 5.4.9-4ubuntu2.4 (cli).

Thank you in advance for your help.

Was it helpful?

Solution

A more generic solution is to put the spec directory into the autoload-dev configuration of your composer.json:

"autoload-dev": {
    "psr-0": {
        "spec\\":""
    }
},

This way, composer will generate the namespace also for the specs, which should be on the root of the repository:

return array(
     'spec\\' => array($baseDir . '/'),
     ...
);

OTHER TIPS

Finally, what I actually did to "solve" my "problem", as suggested by Phil and Sheikh Heera in the comments, is to autoload my namespace so it is recognized by spec.

Here is what I did to make it work :

  • I added the following line to the file `vendor/composer/autoload_namespaces.php` :
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
    //some code
    'spec\\Acme\\Behavior' => array(getcwd()),
    //some code
);
  • Then I created the following folder structure :
    │── spec
    │  └── Acme
    │     └── Behavior
    │        └── FooBehavior.php
  • I declared the namespace in `spec/Acme/Behavior/FooBehavior.php` this way :
namespace spec\Acme\Behavior;
  • And used it in `spec/Acme/Model/Bar/BarSpec.php` as following :
use spec\Acme\Behavior\FooBehavior;

class BarSpec extends FooBehavior{
    //...
}

I know this is not the best practice because everytime someone will be working on this project it will have to reproduce manually the first step. So if you have any better idea, please feel free to comment or post an answer.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top