Getting PHPSpec to work with Laravel

I’ve recently started using PHPSpec to drive my testing efforts in a new Laravel project. The behaviour-driven approach makes a lot of sense to me but I am finding it a little difficult to master as the documentation hasn’t matured yet and as it’s not widely used (yet) there aren’t so many questions and answers to be found on the net.

One problem I ran into early on with my usage of PHPSpec with Laravel was that whilst my tests were passing, I was having an error thrown after the tests had passed in my CLI.

This error would look like:

# phpspec run
100% 4PHP Fatal error: Class 'Eloquent' not found in /path/to/app/models/Schedule.php on line 3

What struck me as weird was that the class being tested was app/Apes/ScheduleCalculator. Now this class used my Schedule model to query the database and the error being thrown referred to the Laravel model.

I wondered around in circles for quite a long time on this trying different approaches of trying to use Eloquent in the test class, in the model (it’s already being used there), and so on. My lack of familiarity with namespaces and OO architecture was definitely showing!

Now that I’ve worked out the fix, I think PHPSpec instantiates my classes in isolation from Laravel, resulting in this error (although this is probably not quite right as if it was wholly in isolation then my ScheduleCalculator class ‘use Schedule’ probably wouldn’t work!). Anyway, hopefully someone can provide me with some elucidation on this one.

The fix

This solution actually came thanks to Ben Constable via a question asked by Adamski on Stack Overflow. Ben Constable has created a package for using PHPSpec in Laravel which you’ll need to install first.

Then you need to edit your phpspec.yml file and include the following declaration:

extensions:
- PhpSpec\Laravel\Extension\LaravelExtension

This instantly fixes these Class ClassName not founderrors.

After fixing this error I quickly realised that you also need to tell PHPSpec what environment you’re using or you’ll encounter more errors. This can be done with the following phpspec.yml declaration.

laravel_extension:
testing_environment: your_local_env_name

I hope that helps someone avoid a potential coding rabbit hole, and would be delighted to hear any feedback or recommendations.

Comments

  • The problem is actually just that you’re extending the Eloquent alias. Just extend IlluminateDatabaseEloquentModel to avoid this kind of trouble.

    Personally, I always do this for all my models. I’m ok with using Facades in my app directory but extending a Facade is a bridge to far for me. They shouldn’t be used like this, imo and only caused more stackoverflow issues then anything else. I’m actually thinking of proposing to remove this facade from Laravel because it’s causing more harm then good.

    • Thanks Dries,

      I’ve found myself getting more used to discovering the full class path and using it that way.

      I have found a number of things difficult with PHPSpec though, especially mocking (for example file uploads has me completely baffled).

      I do love the concept of PHPSpec though, just it being relatively new means there is not as much documentation/stackoverflow as I’d usually rely on.