Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Justus150522's avatar

How to use Route Model Binding while testing Laravel App?

Hello, i want to use model binding inside my testing file. Test looks like that:

public function testAdminOfPartyCanAttachUserToRole()
  {
      $this->seed(PermissionsSeeder::class);
      // GIVEN
      $party = Party::factory()->create();
      $user = User::factory()->create();
      $otherUser = User::factory()->create();
      $party->users()->attach([$user->id, $otherUser->id]);

      session(['party_id' => $party->id]);
      setPermissionsTeamId(session('party_id'));

      $role = Role::where('party_id', $party->id)
      ->where('name', 'Administratorzy')
      ->where('system_role', true)->first();

      $user->assignRole($role);
  
      // WHEN
      $result = $this->actingAs($user)->withMiddleware(['bindings'])->post("api/party/{$party->id}/roles/{$role->id}/attachUsers", [
        'user' => $otherUser,
        'role' => $role, 
      ]);
  
      // THEN
      $result->assertOk(); 
      $this->assertDatabaseHas('model_has_roles', [
        'model_type' => 'App\Models\User',
        'role_id' => $role->id,
        'model_id' => $otherUser->id,
        'party_id' => $party->id,
      ]);
  }

My route looks like that:

    Route::group([
        'middleware' => [
            "throttle:120, 0.5",
        ],
        'prefix' => 'roles'
    ], function ($router) {
        Route::post('/', [RoleController::class, 'create']);
        Route::get('/', [RoleController::class, 'index']);
        Route::patch('/{role}', [RoleController::class, 'update']);
        Route::delete('/{role}', [RoleController::class, 'delete']);
        Route::post('/{role}/attachUsers', [RoleController::class, 'attachUsers'])->name('attach.users');
    });

And my controller function looks like that:

    /**
     * Attach users to specific role
     *
     * @param  Request $request
     * @return \Illuminate\Http\Response
     */
    public function attachUsers(Request $request, Role $role)
    {
        $user = $request->user;
        dump($role);
        $user->assignRole('Administratorzy');

        return response(Response::HTTP_OK);
    }

I am getting error : TypeError: App\Http\Controllers\RoleController::attachUsers(): Argument #2 ($role) must be of type Spatie\Permission\Models\Role, string given, called in /app/api/vendor/laravel/framework/src/Illuminate/Routing/Controller.php on line 54 and defined in /app/api/app/Http/Controllers/RoleController.php:72 So.. i need help with using model binding while testing laravel app. That's all. Thank you. If there has already been a post on this topic before, I'm sorry but I couldn't find a good answer.

0 likes
1 reply
martinbean's avatar

@justus150522 I don’t really understand what you’re trying to do? Just build the URI normally:

$uri = route('party.attachUsers', compact('party', 'role'));

$this
    ->actingAs($user)
    ->post($uri)
    ->assertOk();

The second argument of $this->post is form data; not models to use for route–model binding as you seem to think it is.

Your example also makes no sense as you have {$party->id} and {$role->id} in the URI, but then try and bind user (not “party”) and role. So your tests would be much better if you just stuck to what is actually documented.

Also, you should probably be returning a 201 Created response if you’re creating a new resource, rather than just a 200 OK.

Please or to participate in this conversation.