From 5073021317d57a48497ddbd01809418d69ea8586 Mon Sep 17 00:00:00 2001 From: BacLuc Date: Sun, 29 Jun 2025 22:01:07 +0200 Subject: [PATCH 1/3] AbstractPersistProcessorTest: remove usage of deprecated getMockForAbstractClass Replace the functionality we need in the test with injected callbacks. Issue: #7594 --- .../Util/AbstractPersistProcessorTest.php | 68 +++++++++++++------ 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/api/tests/State/Util/AbstractPersistProcessorTest.php b/api/tests/State/Util/AbstractPersistProcessorTest.php index a1a5d5f3ca..72f2a51cce 100644 --- a/api/tests/State/Util/AbstractPersistProcessorTest.php +++ b/api/tests/State/Util/AbstractPersistProcessorTest.php @@ -2,12 +2,14 @@ namespace App\Tests\State\Util; +use ApiPlatform\Metadata\Operation; use ApiPlatform\Metadata\Patch; use ApiPlatform\Metadata\Post; use ApiPlatform\State\ProcessorInterface; use App\Entity\BaseEntity; use App\State\Util\AbstractPersistProcessor; use App\State\Util\PropertyChangeListener; +use PHPUnit\Framework\MockObject\Exception; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -19,7 +21,14 @@ class AbstractPersistProcessorTest extends TestCase { private MockableClosure|MockObject $closure; private PropertyChangeListener $propertyChangeListener; private AbstractPersistProcessor|MockObject $processor; + private MockableClosure|MockObject $onBefore; + private MockableClosure|MockObject $onAfter; + /** + * @throws WarningException + * @throws Exception + * @throws \ReflectionException + */ protected function setUp(): void { $this->decoratedProcessor = $this->createMock(ProcessorInterface::class); $this->decoratedProcessor->method('process')->willReturnArgument(0); @@ -32,16 +41,18 @@ protected function setUp(): void { afterAction: fn ($data) => $this->closure->call($data), ); - $this->processor = $this->getMockForAbstractClass( - AbstractPersistProcessor::class, - [ - $this->decoratedProcessor, - [$this->propertyChangeListener], - ], - mockedMethods: ['onBefore', 'onAfter'] - ); + $this->onBefore = $this->createMock(MockableClosure::class); + $this->onBefore->method('call')->willReturnArgument(0); - $this->processor->method('onBefore')->willReturnArgument(0); + $this->onAfter = $this->createMock(MockableClosure::class); + $this->onAfter->method('call'); + + $this->processor = new MyEntityPersistProcessor( + decorated: $this->decoratedProcessor, + propertyChangeListeners: [$this->propertyChangeListener], + onBefore: $this->onBefore, + onAfter: $this->onAfter, + ); set_error_handler( /** @@ -58,22 +69,20 @@ protected function tearDown(): void { restore_error_handler(); } + /** + * @throws Exception + */ public function testThrowsIfOnePropertyChangeListenerIsOfWrongType() { $this->expectException(\InvalidArgumentException::class); - $this->getMockForAbstractClass( - AbstractPersistProcessor::class, - [ - $this->decoratedProcessor, - [$this->propertyChangeListener, new \stdClass()], - ] - ); + + new MyEntityPersistProcessor($this->createMock(ProcessorInterface::class), [$this->propertyChangeListener, new \stdClass()], $this->onBefore, $this->onAfter); } public function testCallsOnBeforeCreateAndOnAfterCreateOnPost() { $toPersist = new MyEntity(); - $this->processor->expects(self::once())->method('onBefore')->willReturnArgument(0); - $this->processor->expects(self::once())->method('onAfter'); + $this->onBefore->expects(self::once())->method('call')->willReturnArgument(0); + $this->onAfter->expects(self::once())->method('call'); $this->decoratedProcessor->expects(self::once())->method('process')->willReturnArgument(0); $processResult = $this->processor->process($toPersist, new Post()); @@ -156,14 +165,33 @@ public function testCallPropertyChangeListenerIfPropertyDidChange() { ->method('call') ->willReturnOnConsecutiveCalls($newData, null) ; - $this->processor->expects(self::once())->method('onBefore')->willReturnArgument(0); - $this->processor->expects(self::once())->method('onAfter'); $processResult = $this->processor->process($newData, new Patch(), [], $context); self::assertThat($processResult, self::equalTo($newData)); } } +class MyEntityPersistProcessor extends AbstractPersistProcessor { + public function __construct( + ProcessorInterface $decorated, + array $propertyChangeListeners = [], + private readonly ?MockableClosure $onBefore = null, + private readonly ?MockableClosure $onAfter = null, + ) { + parent::__construct($decorated, $propertyChangeListeners); + } + + public function onBefore($data, Operation $operation, array $uriVariables = [], array $context = []) { + // @noinspection PhpMethodParametersCountMismatchInspection + return $this->onBefore->call($data, $operation, $uriVariables, $context); + } + + public function onAfter($data, Operation $operation, array $uriVariables = [], array $context = []): void { + // @noinspection PhpMethodParametersCountMismatchInspection + $this->onAfter->call($data, $operation, $uriVariables, $context); + } +} + class MyEntity extends BaseEntity { public ?string $name = 'test'; } From 2a37545db7a5fa85bbb026f0c2709b565cc4b9e0 Mon Sep 17 00:00:00 2001 From: BacLuc Date: Sun, 29 Jun 2025 22:08:10 +0200 Subject: [PATCH 2/3] AbstractRemoveProcessorTest: remove usage of deprecated getMockForAbstractClass Replace the functionality we need in the test with injected callbacks. Issue: #7594 --- .../Util/AbstractRemoveProcessorTest.php | 48 +++++++++++++++---- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/api/tests/State/Util/AbstractRemoveProcessorTest.php b/api/tests/State/Util/AbstractRemoveProcessorTest.php index 27b07f37b8..934d588aec 100644 --- a/api/tests/State/Util/AbstractRemoveProcessorTest.php +++ b/api/tests/State/Util/AbstractRemoveProcessorTest.php @@ -3,8 +3,10 @@ namespace App\Tests\State\Util; use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Operation; use ApiPlatform\State\ProcessorInterface; use App\State\Util\AbstractRemoveProcessor; +use PHPUnit\Framework\MockObject\Exception; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -15,23 +17,53 @@ class AbstractRemoveProcessorTest extends TestCase { private MockObject|ProcessorInterface $decoratedProcessor; private AbstractRemoveProcessor|MockObject $processor; + private MockableClosure|MockObject $onBefore; + private MockableClosure|MockObject $onAfter; + + /** + * @throws Exception + */ protected function setUp(): void { $this->decoratedProcessor = $this->createMock(ProcessorInterface::class); - $this->processor = $this->getMockForAbstractClass( - AbstractRemoveProcessor::class, - [ - $this->decoratedProcessor, - ], - mockedMethods: ['onBefore', 'onAfter'] + $this->onBefore = $this->createMock(MockableClosure::class); + $this->onBefore->method('call')->willReturnArgument(0); + + $this->onAfter = $this->createMock(MockableClosure::class); + $this->onAfter->method('call'); + + $this->processor = new MyEntityRemoveProcessor( + decorated: $this->decoratedProcessor, + onBefore: $this->onBefore, + onAfter: $this->onAfter, ); } public function testCallsOnBeforeAndOnAfterOnDelete() { - $this->processor->expects(self::once())->method('onBefore'); - $this->processor->expects(self::once())->method('onAfter'); + $this->onBefore->expects(self::once())->method('call'); + $this->onAfter->expects(self::once())->method('call'); $this->decoratedProcessor->expects(self::once())->method('process'); $this->processor->process(new \stdClass(), new Delete()); } } + +class MyEntityRemoveProcessor extends AbstractRemoveProcessor { + public function __construct( + ProcessorInterface $decorated, + private readonly ?MockableClosure $onBefore = null, + private readonly ?MockableClosure $onAfter = null, + ) { + parent::__construct($decorated); + } + + public function onBefore($data, Operation $operation, array $uriVariables = [], array $context = []): void { + // @noinspection PhpMethodParametersCountMismatchInspection + $this->onBefore->call($data, $operation, $uriVariables, $context); + } + + public function onAfter($data, Operation $operation, array $uriVariables = [], array $context = []): void { + // @noinspection PhpMethodParametersCountMismatchInspection + $this->onAfter->call($data, $operation, $uriVariables, $context); + } +} From 5262ea1d23dea7f9b8774f902463231f7f89d42b Mon Sep 17 00:00:00 2001 From: BacLuc Date: Sun, 29 Jun 2025 22:15:23 +0200 Subject: [PATCH 3/3] Types/Doctrine: remove usage of deprecated getMockForAbstractClass Just instantiate a concrete implementation, we did not verify the interactions. The Postgres implementation does not return the TimeZone when converting to DatabaseValue. Issue: #7594 --- api/tests/Types/Doctrine/BaseDateTypeTestCase.php | 6 +++--- api/tests/Types/Doctrine/UTCDateTimeTypeTest.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/tests/Types/Doctrine/BaseDateTypeTestCase.php b/api/tests/Types/Doctrine/BaseDateTypeTestCase.php index 0e2152468d..68f29c0676 100644 --- a/api/tests/Types/Doctrine/BaseDateTypeTestCase.php +++ b/api/tests/Types/Doctrine/BaseDateTypeTestCase.php @@ -7,21 +7,21 @@ namespace App\Tests\Types\Doctrine; use Doctrine\DBAL\Platforms\AbstractPlatform; +use Doctrine\DBAL\Platforms\PostgreSQLPlatform; use Doctrine\DBAL\Types\ConversionException; use Doctrine\DBAL\Types\Type; use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; abstract class BaseDateTypeTestCase extends TestCase { - protected AbstractPlatform&MockObject $platform; + protected AbstractPlatform $platform; protected Type $type; /** @var non-empty-string */ private string $currentTimezone; protected function setUp(): void { - $this->platform = $this->getMockForAbstractClass(AbstractPlatform::class); + $this->platform = new PostgreSQLPlatform(); $this->currentTimezone = \date_default_timezone_get(); } diff --git a/api/tests/Types/Doctrine/UTCDateTimeTypeTest.php b/api/tests/Types/Doctrine/UTCDateTimeTypeTest.php index 1acc11fd9c..823e6715f7 100644 --- a/api/tests/Types/Doctrine/UTCDateTimeTypeTest.php +++ b/api/tests/Types/Doctrine/UTCDateTimeTypeTest.php @@ -22,7 +22,7 @@ protected function setUp(): void { public function testDateTimeConvertsToDatabaseValue(): void { $date = new \DateTime('1985-09-01 10:10:10'); - $expected = $date->format($this->platform->getDateTimeTzFormatString()); + $expected = $date->format($this->platform->getDateTimeFormatString()); $actual = $this->type->convertToDatabaseValue($date, $this->platform); self::assertEquals($expected, $actual);