From 6312ab5d03eeb42c5a9c3c0e9fafe9245ee2d9a1 Mon Sep 17 00:00:00 2001 From: Anja Leichsenring <aleichsenring@ab-softlab.de> Date: Mon, 28 Sep 2020 23:01:52 +0200 Subject: [PATCH] [TASK] Move CleanerTask tests to functional tests Unit tests requiring database connection and mocking half the world are better of to be reimplemented as functional tests. This has been done to two of CleanerTask tests, which are easier to read and understand now. Resolves: #92437 Releases: master, 10.4 Change-Id: I3c36f2c37050cef3cb1aca96874cb889456552d8 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/65952 Tested-by: TYPO3com <noreply@typo3.com> Tested-by: Oliver Bartsch <bo@cedev.de> Tested-by: Christian Kuhn <lolli@schwarzbu.ch> Reviewed-by: Oliver Bartsch <bo@cedev.de> Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch> --- .../Functional/Task/Pages/CleanerTaskTest.php | 75 +++++++++ .../Pages/DataSet/Assertion/pages_deleted.csv | 4 + .../Assertion/pages_deleted_with_period.csv | 5 + .../Task/Pages/DataSet/Fixtures/pages.csv | 6 + .../Tests/Unit/Task/CleanerTaskTest.php | 157 ------------------ 5 files changed, 90 insertions(+), 157 deletions(-) create mode 100644 typo3/sysext/recycler/Tests/Functional/Task/Pages/CleanerTaskTest.php create mode 100644 typo3/sysext/recycler/Tests/Functional/Task/Pages/DataSet/Assertion/pages_deleted.csv create mode 100644 typo3/sysext/recycler/Tests/Functional/Task/Pages/DataSet/Assertion/pages_deleted_with_period.csv create mode 100644 typo3/sysext/recycler/Tests/Functional/Task/Pages/DataSet/Fixtures/pages.csv delete mode 100644 typo3/sysext/recycler/Tests/Unit/Task/CleanerTaskTest.php diff --git a/typo3/sysext/recycler/Tests/Functional/Task/Pages/CleanerTaskTest.php b/typo3/sysext/recycler/Tests/Functional/Task/Pages/CleanerTaskTest.php new file mode 100644 index 000000000000..cebb28f36deb --- /dev/null +++ b/typo3/sysext/recycler/Tests/Functional/Task/Pages/CleanerTaskTest.php @@ -0,0 +1,75 @@ +<?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! + */ + +namespace TYPO3\CMS\Recycler\Tests\Functional\Task\Pages; + +use TYPO3\CMS\Recycler\Task\CleanerTask; +use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase; + +/** + * Test Case + */ +class CleanerTaskTest extends FunctionalTestCase +{ + protected $coreExtensionsToLoad = ['recycler', 'scheduler']; + + /** + * @test + */ + public function taskRemovesDeletedPages() + { + $this->importCSVDataSet(__DIR__ . '/DataSet/Fixtures/pages.csv'); + $subject = new CleanerTask(); + $subject->setTcaTables(['pages']); + $result = $subject->execute(); + $this->assertCSVDataSet('typo3/sysext/recycler/Tests/Functional/Task/Pages/DataSet/Assertion/pages_deleted.csv'); + self::assertTrue($result); + } + + /** + * @test + */ + public function taskRemovesOnlyPagesLongerDeletedThanPeriod() + { + $this->importCSVDataSet(__DIR__ . '/DataSet/Fixtures/pages.csv'); + $subject = new CleanerTask(); + $subject->setTcaTables(['pages']); + + // this is when the test was created. One of the fixtures (uid 4) has this date + $creationDate = date_create_immutable_from_format('d.m.Y', '28.09.2020')->setTime(0, 0, 0); + // we want to set the period in a way that older records get deleted, but not the one created today + $difference = $creationDate->diff(new \DateTime(), true); + // let's set the amount of days one higher than the reference date + $period = (int)$difference->format('%d') + 1; + $subject->setPeriod($period); + $result = $subject->execute(); + $this->assertCSVDataSet('typo3/sysext/recycler/Tests/Functional/Task/Pages/DataSet/Assertion/pages_deleted_with_period.csv'); + self::assertTrue($result); + } + + /** + * @test + */ + public function taskFailsOnError() + { + $subject = new CleanerTask(); + $GLOBALS['TCA']['not_existing_table']['ctrl']['delete'] = 'deleted'; + $subject->setTcaTables(['not_existing_table']); + $result = $subject->execute(); + self::assertFalse($result); + } +} diff --git a/typo3/sysext/recycler/Tests/Functional/Task/Pages/DataSet/Assertion/pages_deleted.csv b/typo3/sysext/recycler/Tests/Functional/Task/Pages/DataSet/Assertion/pages_deleted.csv new file mode 100644 index 000000000000..075d6d1b2f94 --- /dev/null +++ b/typo3/sysext/recycler/Tests/Functional/Task/Pages/DataSet/Assertion/pages_deleted.csv @@ -0,0 +1,4 @@ +"pages",,,, +,"uid","pid","title","deleted" +,1,0,"root",0 +,2,1,"Page 1",0 diff --git a/typo3/sysext/recycler/Tests/Functional/Task/Pages/DataSet/Assertion/pages_deleted_with_period.csv b/typo3/sysext/recycler/Tests/Functional/Task/Pages/DataSet/Assertion/pages_deleted_with_period.csv new file mode 100644 index 000000000000..f7f6307add8b --- /dev/null +++ b/typo3/sysext/recycler/Tests/Functional/Task/Pages/DataSet/Assertion/pages_deleted_with_period.csv @@ -0,0 +1,5 @@ +"pages",,,,, +,"uid","pid","title","deleted","tstamp" +,1,0,"root",0,0 +,2,1,"Page 1",0,0 +,4,1,"Page 3",1,1601251200 diff --git a/typo3/sysext/recycler/Tests/Functional/Task/Pages/DataSet/Fixtures/pages.csv b/typo3/sysext/recycler/Tests/Functional/Task/Pages/DataSet/Fixtures/pages.csv new file mode 100644 index 000000000000..64fd98e14546 --- /dev/null +++ b/typo3/sysext/recycler/Tests/Functional/Task/Pages/DataSet/Fixtures/pages.csv @@ -0,0 +1,6 @@ +"pages",,,,, +,"uid","pid","title","deleted","tstamp" +,1,0,"root",0,0 +,2,1,"Page 1",0,0 +,3,1,"Page 2",1,1598572800 +,4,1,"Page 3",1,1601251200 diff --git a/typo3/sysext/recycler/Tests/Unit/Task/CleanerTaskTest.php b/typo3/sysext/recycler/Tests/Unit/Task/CleanerTaskTest.php deleted file mode 100644 index 74d90a417a3d..000000000000 --- a/typo3/sysext/recycler/Tests/Unit/Task/CleanerTaskTest.php +++ /dev/null @@ -1,157 +0,0 @@ -<?php - -/* - * 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! - */ - -namespace TYPO3\CMS\Recycler\Tests\Unit\Task; - -use Doctrine\DBAL\DBALException; -use Doctrine\DBAL\Driver\Statement; -use Prophecy\Argument; -use Prophecy\Prophecy\ObjectProphecy; -use TYPO3\CMS\Core\Database\Connection; -use TYPO3\CMS\Core\Database\ConnectionPool; -use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder; -use TYPO3\CMS\Core\Database\Query\QueryBuilder; -use TYPO3\CMS\Core\Database\Query\Restriction\DefaultRestrictionContainer; -use TYPO3\CMS\Core\Tests\Unit\Database\Mocks\MockPlatform; -use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Recycler\Task\CleanerTask; -use TYPO3\TestingFramework\Core\Unit\UnitTestCase; - -/** - * Testcase - */ -class CleanerTaskTest extends UnitTestCase -{ - /** - * @var \PHPUnit\Framework\MockObject\MockObject|CleanerTask - */ - protected $subject; - - /** - * sets up an instance of \TYPO3\CMS\Recycler\Task\CleanerTask - */ - protected function setUp(): void - { - parent::setUp(); - $this->subject = $this->getMockBuilder(CleanerTask::class) - ->setMethods(['dummy']) - ->disableOriginalConstructor() - ->getMock(); - } - - /** - * @test - */ - public function getPeriodCanBeSet() - { - $period = 14; - $this->subject->setPeriod($period); - - self::assertEquals($period, $this->subject->getPeriod()); - } - - /** - * @test - */ - public function getTcaTablesCanBeSet() - { - $tables = ['pages', 'tt_content']; - $this->subject->setTcaTables($tables); - - self::assertEquals($tables, $this->subject->getTcaTables()); - } - - /** - * @test - */ - public function taskBuildsCorrectQuery() - { - $GLOBALS['TCA']['pages']['ctrl']['delete'] = 'deleted'; - $GLOBALS['TCA']['pages']['ctrl']['tstamp'] = 'tstamp'; - - /** @var \PHPUnit\Framework\MockObject\MockObject|CleanerTask $subject */ - $subject = $this->getMockBuilder(CleanerTask::class) - ->setMethods(['getPeriodAsTimestamp']) - ->disableOriginalConstructor() - ->getMock(); - $subject->setTcaTables(['pages']); - $subject->expects(self::once())->method('getPeriodAsTimestamp')->willReturn(400); - - /** @var Connection|ObjectProphecy $connection */ - $connection = $this->prophesize(Connection::class); - $connection->getDatabasePlatform()->willReturn(new MockPlatform()); - $connection->getExpressionBuilder()->willReturn(new ExpressionBuilder($connection->reveal())); - $connection->quoteIdentifier(Argument::cetera())->willReturnArgument(0); - - // TODO: This should rather be a functional test if we need a query builder - // or we should clean up the code itself to not need to mock internal behavior here - - $statementProphet = $this->prophesize(Statement::class); - - $restrictionProphet = $this->prophesize(DefaultRestrictionContainer::class); - $restrictionProphet->removeAll()->willReturn($restrictionProphet->reveal()); - - $queryBuilderProphet = $this->prophesize(QueryBuilder::class); - $queryBuilderProphet->expr()->willReturn( - GeneralUtility::makeInstance(ExpressionBuilder::class, $connection->reveal()) - ); - $queryBuilderProphet->getRestrictions()->willReturn($restrictionProphet->reveal()); - $queryBuilderProphet->createNamedParameter(Argument::cetera())->willReturnArgument(0); - $queryBuilderProphet->delete(Argument::cetera())->willReturn($queryBuilderProphet->reveal()); - $queryBuilderProphet->where(Argument::cetera())->willReturn($queryBuilderProphet->reveal()); - $queryBuilderProphet->execute()->willReturn($statementProphet->reveal()); - - $connectionPool = $this->prophesize(ConnectionPool::class); - $connectionPool->getQueryBuilderForTable('pages')->willReturn($queryBuilderProphet->reveal()); - GeneralUtility::addInstance(ConnectionPool::class, $connectionPool->reveal()); - - self::assertTrue($subject->execute()); - } - - /** - * @test - */ - public function taskFailsOnError() - { - $GLOBALS['TCA']['pages']['ctrl']['delete'] = 'deleted'; - $GLOBALS['TCA']['pages']['ctrl']['tstamp'] = 'tstamp'; - - $this->subject->setTcaTables(['pages']); - - /** @var Connection|ObjectProphecy $connection */ - $connection = $this->prophesize(Connection::class); - $connection->getDatabasePlatform()->willReturn(new MockPlatform()); - $connection->getExpressionBuilder()->willReturn(new ExpressionBuilder($connection->reveal())); - $connection->quoteIdentifier(Argument::cetera())->willReturnArgument(0); - - // TODO: This should rather be a functional test if we need a query builder - // or we should clean up the code itself to not need to mock internal behavior here - $queryBuilder = new QueryBuilder( - $connection->reveal(), - null, - new \Doctrine\DBAL\Query\QueryBuilder($connection->reveal()) - ); - - $connectionPool = $this->prophesize(ConnectionPool::class); - $connectionPool->getQueryBuilderForTable('pages')->willReturn($queryBuilder); - GeneralUtility::addInstance(ConnectionPool::class, $connectionPool->reveal()); - - $connection->executeUpdate(Argument::cetera()) - ->shouldBeCalled() - ->willThrow(new DBALException('testing', 1476122315)); - - self::assertFalse($this->subject->execute()); - } -} -- GitLab