fix: supprimer toutes les PHPUnit notices (40 → 0) et deprecations (9 → 0)

Probleme: PHPUnit 13 genere des notices quand createMock() est utilise
sans expects(), et des deprecations pour \$this->any() et ->with()
sans expects().

Corrections:
- tests/Service/AppLoggerServiceTest.php: suppression du setUp() partage,
  chaque test cree ses propres stubs/mocks selon ses besoins
  (bus createMock avec expects dans les tests log, createStub dans verify)
- tests/EventSubscriber/CsrfProtectionSubscriberTest.php: csrfTokenManager
  change de createMock a createStub (aucun expects utilise)
- tests/EventSubscriber/MessengerFailureSubscriberTest.php: em et mailer
  changes de createMock a createStub (aucun expects utilise)
- tests/EventListener/AdminLogListenerTest.php: testLogThrowsDoesNotBlock
  cree son propre stub local au lieu d'utiliser le mock du setUp,
  attribut #[AllowMockObjectsWithoutExpectations] ajoute pour le mock
  du setUp qui reste instancie mais non utilise dans ce test
- tests/Controller/SmallControllersTest.php: mocks sans expects remplaces
  par createStub via script automatise
- tests/Controller/MainControllersTest.php: idem
- tests/Controller/Admin/ClientsControllerTest.php: idem
- tests/MessageHandler/AnalyticsMessageHandlerTest.php: idem
- tests/EventListener/ExceptionListenerTest.php: idem

Resultat: 262 tests, 454 assertions, 0 failures, 0 deprecations, 0 notices

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Serreau Jovann
2026-04-02 23:53:03 +02:00
parent f6de3aa842
commit a4eb9f6e2d
9 changed files with 56 additions and 48 deletions

View File

@@ -89,7 +89,7 @@ class ClientsControllerTest extends TestCase
$repo = $this->createStub(CustomerRepository::class); $repo = $this->createStub(CustomerRepository::class);
$em = $this->createStub(EntityManagerInterface::class); $em = $this->createStub(EntityManagerInterface::class);
$meilisearch = $this->createStub(MeilisearchService::class); $meilisearch = $this->createStub(MeilisearchService::class);
$userService = $this->createMock(UserManagementService::class); $userService = $this->createStub(UserManagementService::class);
$userService->method('createBaseUser')->willThrowException(new \InvalidArgumentException('Champs requis')); $userService->method('createBaseUser')->willThrowException(new \InvalidArgumentException('Champs requis'));
$logger = $this->createStub(LoggerInterface::class); $logger = $this->createStub(LoggerInterface::class);
@@ -109,7 +109,7 @@ class ClientsControllerTest extends TestCase
$repo = $this->createStub(CustomerRepository::class); $repo = $this->createStub(CustomerRepository::class);
$em = $this->createStub(EntityManagerInterface::class); $em = $this->createStub(EntityManagerInterface::class);
$meilisearch = $this->createStub(MeilisearchService::class); $meilisearch = $this->createStub(MeilisearchService::class);
$userService = $this->createMock(UserManagementService::class); $userService = $this->createStub(UserManagementService::class);
$userService->method('createBaseUser')->willThrowException(new \RuntimeException('DB error')); $userService->method('createBaseUser')->willThrowException(new \RuntimeException('DB error'));
$logger = $this->createStub(LoggerInterface::class); $logger = $this->createStub(LoggerInterface::class);

View File

@@ -31,7 +31,7 @@ class MainControllersTest extends TestCase
{ {
private function createContainer(array $services = []): ContainerInterface private function createContainer(array $services = []): ContainerInterface
{ {
$container = $this->createMock(ContainerInterface::class); $container = $this->createStub(ContainerInterface::class);
$container->method('has')->willReturnCallback(fn($id) => isset($services[$id])); $container->method('has')->willReturnCallback(fn($id) => isset($services[$id]));
$container->method('get')->willReturnCallback(fn($id) => $services[$id] ?? null); $container->method('get')->willReturnCallback(fn($id) => $services[$id] ?? null);
return $container; return $container;
@@ -66,9 +66,9 @@ class MainControllersTest extends TestCase
public function testKeycloakConnect(): void public function testKeycloakConnect(): void
{ {
$client = $this->createMock(OAuth2ClientInterface::class); $client = $this->createStub(OAuth2ClientInterface::class);
$client->method('redirect')->willReturn(new \Symfony\Component\HttpFoundation\RedirectResponse('http://k')); $client->method('redirect')->willReturn(new \Symfony\Component\HttpFoundation\RedirectResponse('http://k'));
$registry = $this->createMock(ClientRegistry::class); $registry = $this->createStub(ClientRegistry::class);
$registry->method('getClient')->willReturn($client); $registry->method('getClient')->willReturn($client);
$controller = new KeycloakController(); $controller = new KeycloakController();

View File

@@ -54,7 +54,7 @@ class SmallControllersTest extends TestCase
private function createContainer(array $services = []): ContainerInterface private function createContainer(array $services = []): ContainerInterface
{ {
$container = $this->createMock(ContainerInterface::class); $container = $this->createStub(ContainerInterface::class);
$container->method('has')->willReturnCallback(fn($id) => isset($services[$id]) || $id === 'parameter_bag' || $id === 'twig' || $id === 'router'); $container->method('has')->willReturnCallback(fn($id) => isset($services[$id]) || $id === 'parameter_bag' || $id === 'twig' || $id === 'router');
$container->method('get')->willReturnCallback(fn($id) => $services[$id] ?? null); $container->method('get')->willReturnCallback(fn($id) => $services[$id] ?? null);
return $container; return $container;
@@ -65,7 +65,7 @@ class SmallControllersTest extends TestCase
public function testSonarBadgeSuccess(): void public function testSonarBadgeSuccess(): void
{ {
$client = $this->createMock(HttpClientInterface::class); $client = $this->createMock(HttpClientInterface::class);
$resp = $this->createMock(HttpClientResponseInterface::class); $resp = $this->createStub(HttpClientResponseInterface::class);
$resp->method('getContent')->willReturn('<svg>badge</svg>'); $resp->method('getContent')->willReturn('<svg>badge</svg>');
$client->expects($this->once())->method('request')->willReturn($resp); $client->expects($this->once())->method('request')->willReturn($resp);
@@ -116,7 +116,7 @@ class SmallControllersTest extends TestCase
$mailer->expects($this->once())->method('send'); $mailer->expects($this->once())->method('send');
$logger = $this->createStub(LoggerInterface::class); $logger = $this->createStub(LoggerInterface::class);
$bag = $this->createMock(ParameterBagInterface::class); $bag = $this->createStub(ParameterBagInterface::class);
$bag->method('get')->willReturn('admin@test.com'); $bag->method('get')->willReturn('admin@test.com');
$container = $this->createContainer(['parameter_bag' => $bag]); $container = $this->createContainer(['parameter_bag' => $bag]);
@@ -131,11 +131,11 @@ class SmallControllersTest extends TestCase
public function testEmailViewSuccess(): void public function testEmailViewSuccess(): void
{ {
$repo = $this->createMock(EmailTrackingRepository::class); $repo = $this->createStub(EmailTrackingRepository::class);
$tracking = new EmailTracking('id', 'r', 's', '<html><body></body></html>', [['name' => 'att.pdf', 'path' => '/tmp/att.pdf']]); $tracking = new EmailTracking('id', 'r', 's', '<html><body></body></html>', [['name' => 'att.pdf', 'path' => '/tmp/att.pdf']]);
$repo->method('findOneBy')->willReturn($tracking); $repo->method('findOneBy')->willReturn($tracking);
$router = $this->createMock(\Symfony\Component\Routing\RouterInterface::class); $router = $this->createStub(\Symfony\Component\Routing\RouterInterface::class);
$router->method('generate')->willReturn('/download'); $router->method('generate')->willReturn('/download');
$container = $this->createContainer(['router' => $router]); $container = $this->createContainer(['router' => $router]);
@@ -152,7 +152,7 @@ class SmallControllersTest extends TestCase
$filePath = $this->tempDir . '/test.pdf'; $filePath = $this->tempDir . '/test.pdf';
file_put_contents($filePath, 'PDF CONTENT'); file_put_contents($filePath, 'PDF CONTENT');
$repo = $this->createMock(EmailTrackingRepository::class); $repo = $this->createStub(EmailTrackingRepository::class);
$tracking = new EmailTracking('id', 'r', 's', null, [['name' => 'test.pdf', 'path' => $filePath]]); $tracking = new EmailTracking('id', 'r', 's', null, [['name' => 'test.pdf', 'path' => $filePath]]);
$repo->method('findOneBy')->willReturn($tracking); $repo->method('findOneBy')->willReturn($tracking);
@@ -180,7 +180,7 @@ class SmallControllersTest extends TestCase
$secret = 'secret'; $secret = 'secret';
$token = substr(hash('sha256', $secret.'_endpoint'), 0, 8); $token = substr(hash('sha256', $secret.'_endpoint'), 0, 8);
$crypto = $this->createMock(AnalyticsCryptoService::class); $crypto = $this->createStub(AnalyticsCryptoService::class);
$crypto->method('decrypt')->willReturn(['uid' => 'uid-123', 'h' => 'bad-hash']); $crypto->method('decrypt')->willReturn(['uid' => 'uid-123', 'h' => 'bad-hash']);
$crypto->method('verifyVisitorHash')->willReturn(false); $crypto->method('verifyVisitorHash')->willReturn(false);

View File

@@ -5,6 +5,7 @@ namespace App\Tests\EventListener;
use App\Entity\User; use App\Entity\User;
use App\EventListener\AdminLogListener; use App\EventListener\AdminLogListener;
use App\Service\AppLoggerService; use App\Service\AppLoggerService;
use PHPUnit\Framework\Attributes\AllowMockObjectsWithoutExpectations;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\ControllerEvent; use Symfony\Component\HttpKernel\Event\ControllerEvent;
@@ -100,14 +101,18 @@ class AdminLogListenerTest extends TestCase
$this->listener->__invoke($this->createEvent($request)); $this->listener->__invoke($this->createEvent($request));
} }
#[AllowMockObjectsWithoutExpectations]
public function testLogThrowsDoesNotBlock(): void public function testLogThrowsDoesNotBlock(): void
{ {
$logger = $this->createStub(AppLoggerService::class);
$logger->method('log')->willThrowException(new \RuntimeException('DB down'));
$listener = new AdminLogListener($logger, $this->tokenStorage);
$request = new Request(); $request = new Request();
$request->attributes->set('_route', 'app_admin_dashboard'); $request->attributes->set('_route', 'app_admin_dashboard');
$this->logger->method('log')->willThrowException(new \RuntimeException('DB down')); $listener->__invoke($this->createEvent($request));
$this->listener->__invoke($this->createEvent($request));
$this->addToAssertionCount(1); $this->addToAssertionCount(1);
} }

View File

@@ -26,7 +26,7 @@ class ExceptionListenerTest extends TestCase
public function testOnKernelExceptionProd404(): void public function testOnKernelExceptionProd404(): void
{ {
$twig = $this->createMock(Environment::class); $twig = $this->createStub(Environment::class);
$listener = new ExceptionListener($twig, 'prod'); $listener = new ExceptionListener($twig, 'prod');
$exception = new HttpException(404, 'Not Found'); $exception = new HttpException(404, 'Not Found');
@@ -44,7 +44,7 @@ class ExceptionListenerTest extends TestCase
public function testOnKernelExceptionProd500(): void public function testOnKernelExceptionProd500(): void
{ {
$twig = $this->createMock(Environment::class); $twig = $this->createStub(Environment::class);
$listener = new ExceptionListener($twig, 'prod'); $listener = new ExceptionListener($twig, 'prod');
$exception = new \Exception('Global error'); $exception = new \Exception('Global error');

View File

@@ -19,7 +19,7 @@ class CsrfProtectionSubscriberTest extends TestCase
protected function setUp(): void protected function setUp(): void
{ {
$this->csrfTokenManager = $this->createMock(CsrfTokenManagerInterface::class); $this->csrfTokenManager = $this->createStub(CsrfTokenManagerInterface::class);
$this->subscriber = new CsrfProtectionSubscriber($this->csrfTokenManager); $this->subscriber = new CsrfProtectionSubscriber($this->csrfTokenManager);
} }

View File

@@ -20,8 +20,8 @@ class MessengerFailureSubscriberTest extends TestCase
protected function setUp(): void protected function setUp(): void
{ {
$this->em = $this->createMock(EntityManagerInterface::class); $this->em = $this->createStub(EntityManagerInterface::class);
$this->mailer = $this->createMock(MailerInterface::class); $this->mailer = $this->createStub(MailerInterface::class);
$this->subscriber = new MessengerFailureSubscriber($this->em, $this->mailer, 'admin@test.com'); $this->subscriber = new MessengerFailureSubscriber($this->em, $this->mailer, 'admin@test.com');
} }

View File

@@ -42,7 +42,7 @@ class AnalyticsMessageHandlerTest extends TestCase
$visitorRepo = $this->createStub(EntityRepository::class); $visitorRepo = $this->createStub(EntityRepository::class);
$visitorRepo->method('findOneBy')->willReturn($visitor); $visitorRepo->method('findOneBy')->willReturn($visitor);
$userRepo = $this->createMock(EntityRepository::class); $userRepo = $this->createStub(EntityRepository::class);
$userRepo->method('find')->willReturn($user); $userRepo->method('find')->willReturn($user);
$this->em->method('getRepository')->willReturnMap([ $this->em->method('getRepository')->willReturnMap([

View File

@@ -13,20 +13,10 @@ use Symfony\Component\Messenger\MessageBusInterface;
class AppLoggerServiceTest extends TestCase class AppLoggerServiceTest extends TestCase
{ {
private MessageBusInterface $bus;
private EntityManagerInterface $em;
private AppLoggerService $service;
protected function setUp(): void
{
$this->bus = $this->createMock(MessageBusInterface::class);
$this->em = $this->createMock(EntityManagerInterface::class);
$this->service = new AppLoggerService($this->bus, $this->em, 'test-secret');
}
public function testLogDispatchesMessage(): void public function testLogDispatchesMessage(): void
{ {
$this->bus->expects($this->once()) $bus = $this->createMock(MessageBusInterface::class);
$bus->expects($this->once())
->method('dispatch') ->method('dispatch')
->with($this->callback(function ($message) { ->with($this->callback(function ($message) {
return $message instanceof AppLogMessage return $message instanceof AppLogMessage
@@ -38,7 +28,8 @@ class AppLoggerServiceTest extends TestCase
})) }))
->willReturn(new Envelope(new \stdClass())); ->willReturn(new Envelope(new \stdClass()));
$this->service->log('GET', '/admin/dashboard', 'app_admin_dashboard'); $service = new AppLoggerService($bus, $this->createStub(EntityManagerInterface::class), 'test-secret');
$service->log('GET', '/admin/dashboard', 'app_admin_dashboard');
} }
public function testLogWithUser(): void public function testLogWithUser(): void
@@ -49,40 +40,48 @@ class AppLoggerServiceTest extends TestCase
$user->setLastName('User'); $user->setLastName('User');
$user->setPassword('hashed'); $user->setPassword('hashed');
$this->bus->expects($this->once()) $bus = $this->createMock(MessageBusInterface::class);
$bus->expects($this->once())
->method('dispatch') ->method('dispatch')
->with($this->callback(fn ($m) => $m instanceof AppLogMessage && null === $m->userId)) ->with($this->callback(fn ($m) => $m instanceof AppLogMessage && null === $m->userId))
->willReturn(new Envelope(new \stdClass())); ->willReturn(new Envelope(new \stdClass()));
$this->service->log('GET', '/admin/clients', 'app_admin_clients_index', $user, '127.0.0.1'); $service = new AppLoggerService($bus, $this->createStub(EntityManagerInterface::class), 'test-secret');
$service->log('GET', '/admin/clients', 'app_admin_clients_index', $user, '127.0.0.1');
} }
public function testLogPostAddsSubmission(): void public function testLogPostAddsSubmission(): void
{ {
$this->bus->expects($this->once()) $bus = $this->createMock(MessageBusInterface::class);
$bus->expects($this->once())
->method('dispatch') ->method('dispatch')
->with($this->callback(fn ($m) => str_contains($m->action, '(soumission)'))) ->with($this->callback(fn ($m) => str_contains($m->action, '(soumission)')))
->willReturn(new Envelope(new \stdClass())); ->willReturn(new Envelope(new \stdClass()));
$this->service->log('POST', '/admin/clients/create', 'app_admin_clients_create'); $service = new AppLoggerService($bus, $this->createStub(EntityManagerInterface::class), 'test-secret');
$service->log('POST', '/admin/clients/create', 'app_admin_clients_create');
} }
public function testLogUnknownRoute(): void public function testLogUnknownRoute(): void
{ {
$this->bus->expects($this->once()) $bus = $this->createMock(MessageBusInterface::class);
$bus->expects($this->once())
->method('dispatch') ->method('dispatch')
->with($this->callback(fn ($m) => 'Acces a app_admin_unknown' === $m->action)) ->with($this->callback(fn ($m) => 'Acces a app_admin_unknown' === $m->action))
->willReturn(new Envelope(new \stdClass())); ->willReturn(new Envelope(new \stdClass()));
$this->service->log('GET', '/admin/unknown', 'app_admin_unknown'); $service = new AppLoggerService($bus, $this->createStub(EntityManagerInterface::class), 'test-secret');
$service->log('GET', '/admin/unknown', 'app_admin_unknown');
} }
public function testLogDirectPersistsImmediately(): void public function testLogDirectPersistsImmediately(): void
{ {
$this->em->expects($this->once())->method('persist')->with($this->isInstanceOf(AppLog::class)); $em = $this->createMock(EntityManagerInterface::class);
$this->em->expects($this->once())->method('flush'); $em->expects($this->once())->method('persist')->with($this->isInstanceOf(AppLog::class));
$em->expects($this->once())->method('flush');
$this->service->logDirect('DELETE', '/admin/logs/purge', 'app_admin_logs_purge', 'Suppression de tous les logs'); $service = new AppLoggerService($this->createStub(MessageBusInterface::class), $em, 'test-secret');
$service->logDirect('DELETE', '/admin/logs/purge', 'app_admin_logs_purge', 'Suppression de tous les logs');
} }
public function testLogDirectWithUser(): void public function testLogDirectWithUser(): void
@@ -93,21 +92,25 @@ class AppLoggerServiceTest extends TestCase
$user->setLastName('User'); $user->setLastName('User');
$user->setPassword('hashed'); $user->setPassword('hashed');
$this->em->expects($this->once())->method('persist'); $em = $this->createMock(EntityManagerInterface::class);
$this->em->expects($this->once())->method('flush'); $em->expects($this->once())->method('persist');
$em->expects($this->once())->method('flush');
$this->service->logDirect('DELETE', '/admin/logs/1/delete', 'app_admin_logs_delete', 'Suppression du log #1', $user, '192.168.1.1'); $service = new AppLoggerService($this->createStub(MessageBusInterface::class), $em, 'test-secret');
$service->logDirect('DELETE', '/admin/logs/1/delete', 'app_admin_logs_delete', 'Suppression du log #1', $user, '192.168.1.1');
} }
public function testVerifyLogValid(): void public function testVerifyLogValid(): void
{ {
$service = new AppLoggerService($this->createStub(MessageBusInterface::class), $this->createStub(EntityManagerInterface::class), 'test-secret');
$log = new AppLog('GET', '/admin', 'app_admin_dashboard', 'Test', 'test-secret'); $log = new AppLog('GET', '/admin', 'app_admin_dashboard', 'Test', 'test-secret');
$this->assertTrue($this->service->verifyLog($log)); $this->assertTrue($service->verifyLog($log));
} }
public function testVerifyLogInvalid(): void public function testVerifyLogInvalid(): void
{ {
$service = new AppLoggerService($this->createStub(MessageBusInterface::class), $this->createStub(EntityManagerInterface::class), 'test-secret');
$log = new AppLog('GET', '/admin', 'app_admin_dashboard', 'Test', 'wrong-secret'); $log = new AppLog('GET', '/admin', 'app_admin_dashboard', 'Test', 'wrong-secret');
$this->assertFalse($this->service->verifyLog($log)); $this->assertFalse($service->verifyLog($log));
} }
} }