userRepository = $this->createMock(UserRepositoryInterface::class); $this->useCase = new AdminUpdateUserRole($this->userRepository, new RolePolicy()); } public function testHandleThrowsNotFoundWhenTargetUserDoesNotExist(): void { $this->userRepository->expects($this->once()) ->method('findById') ->with(42) ->willReturn(null); $this->userRepository->expects($this->never())->method('updateRole'); $this->expectException(NotFoundException::class); $this->useCase->handle(new AdminUpdateUserRoleCommand(1, 42, User::ROLE_EDITOR)); } public function testHandleThrowsWhenActorTriesToModifyOwnRole(): void { $user = $this->makeUser(5, 'alice', User::ROLE_USER); $this->userRepository->expects($this->once()) ->method('findById') ->with(5) ->willReturn($user); $this->userRepository->expects($this->never())->method('updateRole'); $this->expectException(CannotModifyOwnRoleException::class); $this->useCase->handle(new AdminUpdateUserRoleCommand(5, 5, User::ROLE_EDITOR)); } public function testHandleThrowsWhenTargetUserIsAdmin(): void { $admin = $this->makeUser(7, 'root', User::ROLE_ADMIN); $this->userRepository->expects($this->once()) ->method('findById') ->with(7) ->willReturn($admin); $this->userRepository->expects($this->never())->method('updateRole'); $this->expectException(ProtectedAdministratorRoleChangeException::class); $this->useCase->handle(new AdminUpdateUserRoleCommand(1, 7, User::ROLE_EDITOR)); } public function testHandleThrowsWhenRequestedRoleIsNotAssignable(): void { $user = $this->makeUser(8, 'bob', User::ROLE_USER); $this->userRepository->expects($this->once()) ->method('findById') ->with(8) ->willReturn($user); $this->userRepository->expects($this->never())->method('updateRole'); $this->expectException(RoleAssignmentNotAllowedException::class); $this->useCase->handle(new AdminUpdateUserRoleCommand(1, 8, User::ROLE_ADMIN)); } public function testHandleUpdatesRoleAndReturnsTargetUserOnSuccess(): void { $user = $this->makeUser(9, 'charlie', User::ROLE_USER); $this->userRepository->expects($this->once()) ->method('findById') ->with(9) ->willReturn($user); $this->userRepository->expects($this->once()) ->method('updateRole') ->with(9, User::ROLE_EDITOR); $result = $this->useCase->handle(new AdminUpdateUserRoleCommand(1, 9, User::ROLE_EDITOR)); $this->assertSame($user, $result); } private function makeUser(int $id, string $username, string $role): User { return new User($id, $username, sprintf('%s@example.com', $username), 'hashed-password', $role); } }