Easy_solution/tests/Service/AccessTokenServiceTest.php

134 lines
4.7 KiB
PHP

<?php
namespace App\Tests\Service;
use App\Service\AccessTokenService;
use App\Service\LoggerService;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use League\Bundle\OAuth2ServerBundle\Model\AccessToken;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
class AccessTokenServiceTest extends TestCase
{
private AccessTokenService $service;
// Mocks
private MockObject|EntityManagerInterface $entityManager;
private MockObject|LoggerService $loggerService;
protected function setUp(): void
{
$this->entityManager = $this->createMock(EntityManagerInterface::class);
$this->loggerService = $this->createMock(LoggerService::class);
$this->service = new AccessTokenService(
$this->entityManager,
$this->loggerService
);
}
public function testRevokeUserTokensSuccess(): void
{
$userIdentifier = 'test@user.com';
// 1. Create Mock Tokens
$token1 = $this->createMock(AccessToken::class);
$token1->method('getIdentifier')->willReturn('token_1');
$token2 = $this->createMock(AccessToken::class);
$token2->method('getIdentifier')->willReturn('token_2');
// 2. Mock Repository to return these tokens
$repo = $this->createMock(EntityRepository::class);
$repo->expects($this->once())
->method('findBy')
->with(['userIdentifier' => $userIdentifier, 'revoked' => false])
->willReturn([$token1, $token2]);
$this->entityManager->expects($this->once())
->method('getRepository')
->with(AccessToken::class)
->willReturn($repo);
// 3. Expect revoke() to be called on EACH token
$token1->expects($this->once())->method('revoke');
$token2->expects($this->once())->method('revoke');
// 4. Expect success logs
$this->loggerService->expects($this->exactly(2))
->method('logTokenRevocation')
->with(
'Access token revoked for user',
$this->callback(function ($context) use ($userIdentifier) {
return $context['user_identifier'] === $userIdentifier
&& in_array($context['token_id'], ['token_1', 'token_2']);
})
);
// 5. Run
$this->service->revokeUserTokens($userIdentifier);
}
public function testRevokeUserTokensHandlesException(): void
{
$userIdentifier = 'fail@user.com';
// 1. Create a Token that fails to revoke
$tokenBad = $this->createMock(AccessToken::class);
$tokenBad->method('getIdentifier')->willReturn('bad_token');
// Throw exception when revoke is called
$tokenBad->expects($this->once())
->method('revoke')
->willThrowException(new \Exception('DB Connection Lost'));
// 2. Create a Token that works (to prove loop continues, if applicable)
// Your code uses try-catch inside the loop, so it SHOULD continue.
$tokenGood = $this->createMock(AccessToken::class);
$tokenGood->method('getIdentifier')->willReturn('good_token');
$tokenGood->expects($this->once())->method('revoke');
// 3. Mock Repository
$repo = $this->createMock(EntityRepository::class);
$repo->method('findBy')->willReturn([$tokenBad, $tokenGood]);
$this->entityManager->method('getRepository')->willReturn($repo);
// 4. Expect Logger calls
// Expect 1 Error log
$this->loggerService->expects($this->once())
->method('logError')
->with(
'Error revoking access token: DB Connection Lost',
['user_identifier' => $userIdentifier, 'token_id' => 'bad_token']
);
// Expect 1 Success log (for the good token)
$this->loggerService->expects($this->once())
->method('logTokenRevocation')
->with(
'Access token revoked for user',
['user_identifier' => $userIdentifier, 'token_id' => 'good_token']
);
// 5. Run
$this->service->revokeUserTokens($userIdentifier);
}
public function testRevokeUserTokensDoesNothingIfNoneFound(): void
{
$userIdentifier = 'ghost@user.com';
$repo = $this->createMock(EntityRepository::class);
$repo->method('findBy')->willReturn([]); // Empty array
$this->entityManager->method('getRepository')->willReturn($repo);
// Expect NO logs
$this->loggerService->expects($this->never())->method('logTokenRevocation');
$this->loggerService->expects($this->never())->method('logError');
$this->service->revokeUserTokens($userIdentifier);
}
}