Skip to content

Commit

Permalink
[TASK] Avoid phpunit getMockForAbstractClass()
Browse files Browse the repository at this point in the history
Deprecated with phpunit 11. Adapt to
fixture classes to test details of abstracts.

Resolves: #103228
Releases: main
Change-Id: Ic0cd4541856beb45775d50d22b95be687888373a
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/83160
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Oliver Klee <typo3-coding@oliverklee.de>
Reviewed-by: Stefan Bürk <stefan@buerk.tech>
Reviewed-by: Oliver Klee <typo3-coding@oliverklee.de>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: core-ci <typo3@b13.com>
Tested-by: Stefan Bürk <stefan@buerk.tech>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
  • Loading branch information
lolli42 committed Feb 28, 2024
1 parent f7a1b5e commit 2cff779
Show file tree
Hide file tree
Showing 10 changed files with 371 additions and 656 deletions.
354 changes: 50 additions & 304 deletions typo3/sysext/form/Tests/Unit/Domain/Finishers/AbstractFinisherTest.php

Large diffs are not rendered by default.

@@ -0,0 +1,57 @@
<?php

declare(strict_types=1);

/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/

/*
* Inspired by and partially taken from the Neos.Form package (www.neos.io)
*/

namespace TYPO3\CMS\Form\Tests\Unit\Domain\Finishers\Fixtures;

use TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher;
use TYPO3\CMS\Form\Domain\Runtime\FormRuntime;

final class AbstractFinisherFixture extends AbstractFinisher
{
public $options = [];
public $defaultOptions = [];
public $finisherContext;

protected function executeInternal()
{
return null;
}

public function parseOption(string $optionName)
{
return parent::parseOption($optionName);
}

protected function translateFinisherOption(
$subject,
FormRuntime $formRuntime,
string $optionName,
$optionValue,
array $translationOptions
) {
return $subject;
}

public function substituteRuntimeReferences($needle, FormRuntime $formRuntime)
{
return parent::substituteRuntimeReferences($needle, $formRuntime);
}
}
149 changes: 36 additions & 113 deletions typo3/sysext/form/Tests/Unit/Domain/FormElements/AbstractSectionTest.php
Expand Up @@ -24,10 +24,9 @@
use TYPO3\CMS\Form\Domain\Exception\TypeDefinitionNotValidException;
use TYPO3\CMS\Form\Domain\Model\FormDefinition;
use TYPO3\CMS\Form\Domain\Model\FormElements\AbstractSection;
use TYPO3\CMS\Form\Domain\Model\FormElements\Section;
use TYPO3\CMS\Form\Domain\Model\FormElements\UnknownFormElement;
use TYPO3\CMS\Form\Tests\Unit\Domain\FormElements\Fixtures\AbstractSectionFixture;
use TYPO3\CMS\Form\Tests\Unit\Domain\FormElements\Fixtures\TestingFormElement;
use TYPO3\CMS\Form\Tests\Unit\Domain\FormElements\Fixtures\TestingSection;
use TYPO3\TestingFramework\Core\Unit\UnitTestCase;

final class AbstractSectionTest extends UnitTestCase
Expand All @@ -39,73 +38,36 @@ public function constructThrowsExceptionWhenIdentifierIsEmpty(): void
{
$this->expectException(IdentifierNotValidException::class);
$this->expectExceptionCode(1477082501);

// Section inherits from AbstractSection and serves as concrete implementation
new Section('', 'foobar');
new AbstractSectionFixture('', 'foobar');
}

#[Test]
public function constructMustNotThrowExceptionWhenIdentifierIsNonEmptyString(): void
{
$section = new Section('foobar', 'foobar');
self::assertInstanceOf(AbstractSection::class, $section);
$subject = new AbstractSectionFixture('foobar', '');
self::assertInstanceOf(AbstractSection::class, $subject);
}

#[Test]
public function createElementThrowsExceptionIfTypeDefinitionNotFoundAndSkipUnknownElementsIsFalse(): void
{
$rootForm = $this->getMockBuilder(FormDefinition::class)
->onlyMethods(['getRenderingOptions', 'getTypeDefinitions'])
->disableOriginalConstructor()
->getMock();
$rootForm
->method('getRenderingOptions')
->willReturn(['skipUnknownElements' => false]);
$rootForm
->method('getTypeDefinitions')
->willReturn([]);

$mockAbstractSection = $this->getAccessibleMockForAbstractClass(
AbstractSection::class,
[],
'',
false,
false,
true,
[
'getRootForm',
]
);

$mockAbstractSection
->expects(self::once())
->method('getRootForm')
->willReturn($rootForm);

$rootForm = $this->createMock(FormDefinition::class);
$this->expectException(TypeDefinitionNotFoundException::class);
$this->expectExceptionCode(1382364019);

$mockAbstractSection->_call('createElement', '', '');
$subject = new AbstractSectionFixture('identifier', '');
$subject->setParentRenderable($rootForm);
$subject->createElement('', '');
}

#[Test]
public function createElementReturnsUnknownElementsIfTypeDefinitionIsNotFoundAndSkipUnknownElementsIsTrue(): void
{
$rootForm = $this->getMockBuilder(FormDefinition::class)
->onlyMethods(['getRenderingOptions', 'getTypeDefinitions'])
->disableOriginalConstructor()
->getMock();
$rootForm
->method('getRenderingOptions')
->willReturn(['skipUnknownElements' => true]);
$rootForm
->method('getTypeDefinitions')
->willReturn([]);
$section = new TestingSection($rootForm);

$rootForm = $this->createMock(FormDefinition::class);
$rootForm->method('getRenderingOptions')->willReturn(['skipUnknownElements' => true]);
GeneralUtility::addInstance(UnknownFormElement::class, new UnknownFormElement('foo', 'bar'));
$result = $section->createElement('foo', 'bar');

$subject = new AbstractSectionFixture('testing', '');
$subject->setParentRenderable($rootForm);
$result = $subject->createElement('foo', 'bar');
self::assertInstanceOf(UnknownFormElement::class, $result);
self::assertSame('foo', $result->getIdentifier());
self::assertSame('bar', $result->getType());
Expand All @@ -114,89 +76,50 @@ public function createElementReturnsUnknownElementsIfTypeDefinitionIsNotFoundAnd
#[Test]
public function createElementThrowsExceptionIfTypeDefinitionIsNotSet(): void
{
$rootForm = $this->getMockBuilder(FormDefinition::class)
->onlyMethods(['getRenderingOptions', 'getTypeDefinitions'])
->disableOriginalConstructor()
->getMock();
$rootForm
->method('getRenderingOptions')
->willReturn(['skipUnknownElements' => true]);
$rootForm
->method('getTypeDefinitions')
->willReturn(['foobar' => []]);
$section = new TestingSection($rootForm);

$this->expectException(TypeDefinitionNotFoundException::class);
$this->expectExceptionCode(1325689855);

$section->createElement('id', 'foobar');
$rootForm = $this->createMock(FormDefinition::class);
$rootForm->method('getTypeDefinitions')->willReturn(['foobar' => []]);
$subject = new AbstractSectionFixture('testing', '');
$subject->setParentRenderable($rootForm);
$subject->createElement('id', 'foobar');
}

#[Test]
public function createElementThrowsExceptionIfTypeDefinitionNotInstanceOfFormElementInterface(): void
{
$rootForm = $this->getMockBuilder(FormDefinition::class)
->onlyMethods(['getRenderingOptions', 'getTypeDefinitions'])
->disableOriginalConstructor()
->getMock();
$rootForm
->method('getRenderingOptions')
->willReturn([]);
$rootForm
->method('getTypeDefinitions')
->willReturn(
[
'foobar' => [
'implementationClassName' => self::class,
],
]
);
$section = new TestingSection($rootForm);

GeneralUtility::addInstance(self::class, $this);

$this->expectException(TypeDefinitionNotValidException::class);
$this->expectExceptionCode(1327318156);
$section->createElement('id', 'foobar');
$rootForm = $this->createMock(FormDefinition::class);
$rootForm->method('getTypeDefinitions')->willReturn([
'foobar' => [
'implementationClassName' => self::class,
],
]);
$subject = new AbstractSectionFixture('testing', '');
$subject->setParentRenderable($rootForm);
GeneralUtility::addInstance(self::class, $this);
$subject->createElement('id', 'foobar');
}

#[Test]
public function createElementExpectedToAddAndInitializeElement(): void
{
$implementationMock = $this->createPartialMock(TestingFormElement::class, ['setOptions', 'initializeFormElement']);

$implementationMock = $this->createMock(TestingFormElement::class);
$typeDefinition = [
'foo' => 'bar',
'implementationClassName' => get_class($implementationMock),
'fizz' => 'buzz',
];

$typeDefinitionWithoutImplementationClassName = $typeDefinition;
unset($typeDefinitionWithoutImplementationClassName['implementationClassName']);

$implementationMock
->expects(self::once())
->method('initializeFormElement');

$implementationMock
->expects(self::once())
->method('setOptions')
->with($typeDefinitionWithoutImplementationClassName);

$rootForm = $this->getMockBuilder(FormDefinition::class)
->onlyMethods(['getRenderingOptions', 'getTypeDefinitions'])
->disableOriginalConstructor()
->getMock();
$rootForm
->method('getRenderingOptions')
->willReturn([]);
$rootForm
->method('getTypeDefinitions')
->willReturn(['foobar' => $typeDefinition]);
$section = new TestingSection($rootForm);

$implementationMock->expects(self::once())->method('initializeFormElement');
$implementationMock->expects(self::once())->method('setOptions')->with($typeDefinitionWithoutImplementationClassName);
$rootForm = $this->createMock(FormDefinition::class);
$rootForm->method('getTypeDefinitions')->willReturn(['foobar' => $typeDefinition]);
$subject = new AbstractSectionFixture('testing', '');
$subject->setParentRenderable($rootForm);
GeneralUtility::addInstance(get_class($implementationMock), $implementationMock);

$section->createElement('id', 'foobar');
$subject->createElement('id', 'foobar');
}
}
Expand Up @@ -17,21 +17,6 @@

namespace TYPO3\CMS\Form\Tests\Unit\Domain\FormElements\Fixtures;

use TYPO3\CMS\Form\Domain\Model\FormDefinition;
use TYPO3\CMS\Form\Domain\Model\FormElements\AbstractSection;

/**
* Testing subclass of the abstract class.
*/
class TestingSection extends AbstractSection
{
public function __construct(private readonly FormDefinition $rootForm)
{
parent::__construct('testing_section', '');
}

public function getRootForm(): FormDefinition
{
return $this->rootForm;
}
}
final class AbstractSectionFixture extends AbstractSection {}

0 comments on commit 2cff779

Please sign in to comment.