zenith707's avatar

Feature test returning "role does not exists" with Spatie Laravel Permission

Quite simple, but not so simple. Here is the test that fails:

public function test_new_users_can_register(): void
    {
        $response = $this->post('/register', [
            'first_name' => 'Test',
            'last_name' => 'User',
            'email' => '[email protected]',
            'password' => 'password',
            'password_confirmation' => 'password',
        ]);

        $user = User::where('email', '[email protected]')->get();

        $user->assignRole('Admin'); // fails here

        $this->assertAuthenticated();
        $response->assertRedirect(RouteServiceProvider::HOME);
    }

Method Illuminate\Database\Eloquent\Collection::assignRole does not exist.

I have tried adding the HasRoles trait to the test class. User model also has the trait. Everything works fine on the frontend, but the testing environment is not recognising it. Any idea?

Full code -

namespace Tests\Feature\Auth;

use Tests\TestCase;
use App\Models\User;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Spatie\Permission\Traits\HasRoles;

class RegistrationTest extends TestCase
{
    use RefreshDatabase, HasRoles;

	public function test_new_users_can_register(): void
    {
        $response = $this->post('/register', [
            'first_name' => 'Test',
            'last_name' => 'User',
            'email' => '[email protected]',
            'password' => 'password',
            'password_confirmation' => 'password',
        ]);

        $user = User::where('email', '[email protected]')->get();

        $user->assignRole('Admin'); // fails here

        $this->assertAuthenticated();
        $response->assertRedirect(RouteServiceProvider::HOME);
    }
namespace App\Models;

use Carbon\Carbon;
use Laravel\Sanctum\HasApiTokens;
use Spatie\Permission\Traits\HasRoles;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable implements MustVerifyEmail
{
    use HasApiTokens, HasFactory, Notifiable, HasRoles;

etc...
0 likes
4 replies
tykus's avatar

You need to seed the Admin role in the test; but I don't understand why you're assigning the role in the test anyway. What are you trying to prove with this test???

zenith707's avatar

@tykus Simple. User signs up and gets assigned a role immediately upon doing so.

tykus's avatar

@zenith707 sure, but in the implementation logic, not in the test example. You are assigning the Role after the TestResponse has been returned anyway, so what is the point of (i) fetching the User instance and (ii) assigning a Role inside the test example???

Please or to participate in this conversation.