Trait not found inside Laravel 5 unit tests

John Dorean picture John Dorean · Jul 6, 2015 · Viewed 7.5k times · Source

I'm writing some unit tests to test the API endpoints in my Laravel 5 application, and a lot of endpoints require user authentication. Instead of having the same user account creation code in every test, I wanted to define a RegistersUsers trait to use on the test classes, which will have a registerUser() method.

The directory structure of my tests directory is like so:

/tests
    /Traits
        RegistersUsers.php
    TestCase.php
    UserTest.php

I've namespaced TestCase.php and UserTest.php by adding this namespace declaration:

namespace MyappTests;

and I've namespaced RegistersUsers.php like so:

namespace MyappTests\Traits;

My UserTest looks like this, with the namespace and the use declaration so that I can leverage RegistersUsers.

<?php

namespace MyappTests;

use MyappTests\Traits\RegistersUsers;

class UserTest extends TestCase
{
    use RegistersUsers;

    // ... rest of the class

However, when I run the test, PHPUnit dies with the fatal error:

Trait 'MyappTests\Traits\RegistersUsers' not found in /home/vagrant/demo-app-net/tests/UserTest.php on line 9

As far as I can tell, my namespacing is correct and my trait should be found. I've been going around in circles with this and can't seem to figure it out.

Answer

user1669496 picture user1669496 · Jul 6, 2015

I'm guessing having the trait in the traits folder, the trait is no longer accounted for in your autoloader.

In order to correct this, you should open up composer.json, find the sectionfor autoload-dev and change it to something like the following...

"autoload-dev": {
    "classmap": [
        "tests/TestCase.php",
        "tests/Traits/"
    ]
},

And that should add any traits you have in that folder to the autloader.

Edit

Some additional ideas were brought up in the comments. If you are going to be maintaining proper folder/namespace structure, it would be a good idea to use psr-4 autoloading rather than maintaining the class map.

"autoload-dev": {
    "psr-4": {
        "MyappTests\\": "tests/"
    }
},

Also, rather than put logic in a trait to register a user for use with testing, when you extend TestCase, it brings in a helper method for logging in as a certain user. You'd use it like so...

$user = User::find($id);
$this->be($user);