2 min read

Auto Trait Invocation with Laravel + Pest

My app uses the spatie/laravel-permission package to manage roles and permissions, and PestPHP for testing.

It’s normal to set up users, roles, and permissions for each test. I created SetupRoles trait to accomodate this.

trait SetUpRoles
     * @var \Spatie\Permission\Models\Role
    protected $superAdminRole;
    // the rest of code
    public function setUpRoles(): void
        $this->superAdminRole = Role::findOrCreate(RoleEnum::SUPERADMIN->value, 'web');
        // the rest of code

Normally, we would do this manually in each test file:

beforeEach(function () {

However, we would prefer to automatically run setUpRoles() for each test, similar to how the RefreshDatabase trait works.

To achieve this, we need to extend setUpTraits in our tests/TestCase like so:

namespace Tests;
use Tests\Feature\Concerns\SetUpRoles;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
abstract class TestCase extends BaseTestCase
    use CreatesApplication;
     * Boot the testing helper traits.
     * @return array
    protected function setUpTraits()
        $uses = parent::setUpTraits();
        if (isset($uses[SetUpRoles::class])) {
            /** @disregard */

Essentially, this scans all used classes from the test file. If SetUpRoles trait is detected, it calls the setUpRoles method.

protected function setUpTraits()
    $uses = array_flip(class_uses_recursive(static::class));
    if (isset($uses[RefreshDatabase::class])) {
    // ... rest of the code

Above is how RefreshDatabase is called automatically from our test.

Finally, we just need to register our trait inside tests/Pest.php like this:

)->in('Feature', 'Unit');

Done. Now, you don’t need to reference the traits in your test files anymore.