ui = $this->getMockBuilder(CronUIInterface::class)->disableOriginalConstructor()->getMock(); $this->logger = $this->getMockBuilder(LoggerInterface::class)->disableOriginalConstructor()->getMock(); $this->fileRepository = $this->getMockBuilder(FileRepository::class)->disableOriginalConstructor()->getMock(); $this->connection = $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock(); $this->storage = $this->getMockBuilder(LocalStorage::class)->disableOriginalConstructor()->getMock(); } private function getMockFor(string $method): MockObject|TestableCleanTempFile { $cleanTempFiles = $this->getMockBuilder(TestableCleanTempFile::class) ->setConstructorArgs([$this->connection, $this->fileRepository, $this->storage]) ->setMethodsExcept([$method, 'setUI', 'setLoggerInterface']) ->getMock(); $cleanTempFiles->setUI($this->ui); $cleanTempFiles->setLoggerInterface($this->logger); return $cleanTempFiles; } public function testPreview(): void { DatesUtils::setFakeDatetime('2022-01-08 00:00:00'); $maxDate = DatesUtils::new(); $maxDate->sub(new \DateInterval('P60D')); $cleanTempFiles = $this->getMockFor('preview'); $file1 = $this->getMockBuilder(File::class)->getMock(); $file1->method('getSlug')->willReturn('/foo'); $file2 = $this->getMockBuilder(File::class)->getMock(); $file2->method('getSlug')->willReturn('/bar'); $file3 = $this->getMockBuilder(File::class)->getMock(); $file3->method('getSlug')->willReturn('/foo/bar'); $cleanTempFiles->method('listFilesToDelete')->with($maxDate)->willReturn([$file1, $file2, $file3]); $this->ui->expects(self::atLeastOnce())->method('print')->withConsecutive( ['3 temporary files to be removed'], ['> Printing the first and last 50 :'], [' * /foo'], [' * /bar'], [' * /foo/bar'] ); $cleanTempFiles->preview(); } public function testExecute(): void { DatesUtils::setFakeDatetime('2022-01-08 00:00:00'); $maxDate = DatesUtils::new(); $maxDate->sub(new \DateInterval('P60D')); $cleanTempFiles = $this->getMockFor('execute'); $files = [ $this->getMockBuilder(File::class)->getMock(), $this->getMockBuilder(File::class)->getMock(), $this->getMockBuilder(File::class)->getMock(), ]; $cleanTempFiles->method('listFilesToDelete')->with($maxDate)->willReturn($files); $cleanTempFiles->expects(self::once())->method('deleteFiles')->with($files); $cleanTempFiles->execute(); } public function testListFilesToDelete(): void { $cleanTempFiles = $this->getMockFor('listFilesToDelete'); DatesUtils::setFakeDatetime('2023-05-01 00:00:00'); $maxDate = DatesUtils::new(); // Mock la méthode getQueryBuilder() $queryBuilder = $this->getMockBuilder(QueryBuilder::class) ->disableOriginalConstructor() ->getMock(); $this->fileRepository->method('createQueryBuilder')->with('f')->willReturn($queryBuilder); // S'attend à ce que la méthode select() soit appelée $queryBuilder->expects($this->once()) ->method('select'); // S'attend à ce que la méthode getQueryConditions() soit appelée avec $maxDate $cleanTempFiles->expects($this->once()) ->method('getQueryConditions') ->with($queryBuilder, $maxDate); // Mock la méthode getQuery() et getResult() pour renvoyer un tableau vide $query = $this->getMockBuilder(Query::class) ->disableOriginalConstructor() ->getMock(); $query->expects($this->once()) ->method('getResult') ->willReturn([]); $queryBuilder->expects($this->once()) ->method('getQuery') ->willReturn($query); // Appeler la méthode listFilesToDelete() $result = $cleanTempFiles->listFilesToDelete($maxDate); // Vérifier que la méthode getResult() a été appelée sur la requête $this->assertEquals([], $result); } public function testDeleteFiles(): void { $cleanTempFiles = $this->getMockFor('deleteFiles'); $file1 = $this->getMockBuilder(File::class)->getMock(); $file1->method('getId')->willReturn(1); $file2 = $this->getMockBuilder(File::class)->getMock(); $file2->method('getId')->willReturn(2); $file3 = $this->getMockBuilder(File::class)->getMock(); $file3->method('getId')->willReturn(3); $files = [$file1, $file2, $file3]; $this->connection->expects($this->exactly(3))->method('beginTransaction'); $this->connection->expects($this->once())->method('setAutoCommit')->with(false); $queryBuilder = $this->getMockBuilder(QueryBuilder::class)->disableOriginalConstructor()->getMock(); $this->fileRepository->expects($this->once())->method('createQueryBuilder')->with('f')->willReturn($queryBuilder); $queryBuilder ->expects(self::exactly(3)) ->method('delete') ->willReturnSelf(); $queryBuilder ->expects(self::exactly(3)) ->method('where') ->with('f.id = :id') ->willReturnSelf(); $queryBuilder ->expects(self::exactly(3)) ->method('setParameter') ->withConsecutive(['id', 1], ['id', 2], ['id', 3]); $this->storage ->expects(self::exactly(3)) ->method('hardDelete') ->withConsecutive([$file1], [$file1], [$file3]); $this->connection->expects($this->exactly(3))->method('commit'); $this->connection->expects($this->never())->method('rollback'); $this->logger->expects(self::atLeastOnce())->method('info')->withConsecutive( ['3 temporary files to be removed'], ['Deleting files...'], ['3 files deleted'] ); $cleanTempFiles->deleteFiles($files); } public function testDeleteFilesWithNonBlockingErrors(): void { $cleanTempFiles = $this->getMockFor('deleteFiles'); $file1 = $this->getMockBuilder(File::class)->getMock(); $file1->method('getId')->willReturn(1); $file2 = $this->getMockBuilder(File::class)->getMock(); $file2->method('getId')->willReturn(2); $files = [$file1, $file2]; $this->connection->expects($this->exactly(2))->method('beginTransaction'); $this->connection->expects($this->once())->method('setAutoCommit')->with(false); $queryBuilder = $this->getMockBuilder(QueryBuilder::class)->disableOriginalConstructor()->getMock(); $this->fileRepository->expects($this->once())->method('createQueryBuilder')->with('f')->willReturn($queryBuilder); $queryBuilder ->expects(self::never()) ->method('delete') ->willReturnSelf(); $this->storage ->expects(self::exactly(2)) ->method('hardDelete') ->willReturnCallback(function ($file) { switch ($file->getId()) { case 1: throw new \RuntimeException('Some error'); case 2: throw new \InvalidArgumentException('Some other error'); } }); $this->connection->expects($this->never())->method('commit'); $this->connection->expects($this->exactly(2))->method('rollback'); $this->logger->expects(self::atLeastOnce())->method('info')->withConsecutive( ['2 temporary files to be removed'], ['Deleting files...'], ['0 files deleted'] ); $this->logger ->expects(self::exactly(2)) ->method('error') ->withConsecutive( ['ERROR : Some error'], ['ERROR : Some other error'], ); $cleanTempFiles->deleteFiles($files); } public function testDeleteFilesWithBlockingError(): void { $cleanTempFiles = $this->getMockFor('deleteFiles'); $file1 = $this->getMockBuilder(File::class)->getMock(); $file1->method('getId')->willReturn(1); $files = [$file1]; $this->connection->expects($this->once())->method('beginTransaction'); $this->connection->expects($this->once())->method('setAutoCommit')->with(false); $queryBuilder = $this->getMockBuilder(QueryBuilder::class)->disableOriginalConstructor()->getMock(); $this->fileRepository->expects($this->once())->method('createQueryBuilder')->with('f')->willReturn($queryBuilder); $queryBuilder ->expects(self::never()) ->method('delete') ->willReturnSelf(); $this->storage ->expects(self::exactly(1)) ->method('hardDelete') ->willReturnCallback(function ($file) { switch ($file->getId()) { case 1: throw new \Exception('Some unknown error'); } }); $this->connection->expects($this->never())->method('commit'); $this->connection->expects($this->once())->method('rollback'); $this->logger->expects(self::atLeastOnce())->method('info')->withConsecutive( ['1 temporary files to be removed'], ['Deleting files...'], ); $this->expectException(\Exception::class); $cleanTempFiles->deleteFiles($files); } public function testGetQueryConditions(): void { DatesUtils::setFakeDatetime('2022-01-08 00:00:00'); $cleanTempFiles = $this->getMockFor('getQueryConditions'); $maxDate = DatesUtils::new(); $maxDate->sub(new \DateInterval('P60D')); $queryBuilder = $this->getMockBuilder(QueryBuilder::class)->disableOriginalConstructor()->getMock(); $expr = $this->getMockBuilder(Expr::class)->disableOriginalConstructor()->getMock(); $queryBuilder->method('expr')->willReturn($expr); $cmp1 = $this->getMockBuilder(Comparison::class)->disableOriginalConstructor()->getMock(); $cmp2 = $this->getMockBuilder(Comparison::class)->disableOriginalConstructor()->getMock(); $cmp3 = $this->getMockBuilder(Comparison::class)->disableOriginalConstructor()->getMock(); $cmp4 = $this->getMockBuilder(Comparison::class)->disableOriginalConstructor()->getMock(); $expr->expects(self::exactly(3))->method('eq')->willReturnMap( [ ['f.isTemporaryFile', ':temporaryTrue', $cmp1], ['f.status', ':status', $cmp2], ['f.host', ':host', $cmp3], ] ); $expr->expects(self::once())->method('lt')->with('f.createDate', ':maxDate')->willReturn($cmp4); $expr->expects(self::once())->method('isNull')->with('f.createDate')->willReturn('f.createDate is null'); $orX1 = $this->getMockBuilder(Expr\Orx::class)->disableOriginalConstructor()->getMock(); $orX2 = $this->getMockBuilder(Expr\Orx::class)->disableOriginalConstructor()->getMock(); $expr->expects(self::exactly(2))->method('orX')->willReturnMap( [ [$cmp1, $cmp2, $orX1], [$cmp4, 'f.createDate is null', $orX2], ] ); $queryBuilder ->expects(self::exactly(3)) ->method('andWhere') ->withConsecutive( [$orX1], [$cmp3], [$orX2], ) ->willReturnSelf(); $queryBuilder ->expects(self::exactly(4)) ->method('setParameter') ->withConsecutive( ['temporaryTrue', true], ['host', FileHostEnum::AP2I], ['status', FileStatusEnum::DELETED], ['maxDate', '2021-11-09'], ) ->willReturnSelf(); $cleanTempFiles->getQueryConditions($queryBuilder, $maxDate); } }