diff --git a/dev/tests/integration/testsuite/Magento/Framework/Code/GeneratorTest.php b/dev/tests/integration/testsuite/Magento/Framework/Code/GeneratorTest.php index d74a83c339326..a43013860c79c 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Code/GeneratorTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Code/GeneratorTest.php @@ -5,12 +5,13 @@ */ namespace Magento\Framework\Code; -use Magento\Framework\Code\Generator; +use Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceFactoryGenerator; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\Filesystem; use Magento\Framework\Interception\Code\Generator as InterceptionGenerator; use Magento\Framework\ObjectManager\Code\Generator as DIGenerator; -use Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceFactoryGenerator; use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; require_once __DIR__ . '/GeneratorTest/SourceClassWithNamespace.php'; require_once __DIR__ . '/GeneratorTest/ParentClassWithNamespace.php'; @@ -18,60 +19,77 @@ /** * @magentoAppIsolation enabled + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class GeneratorTest extends \PHPUnit\Framework\TestCase +class GeneratorTest extends TestCase { - const CLASS_NAME_WITH_NAMESPACE = \Magento\Framework\Code\GeneratorTest\SourceClassWithNamespace::class; + const CLASS_NAME_WITH_NAMESPACE = GeneratorTest\SourceClassWithNamespace::class; /** - * @var \Magento\Framework\Code\Generator + * @var Generator */ protected $_generator; /** - * @var \Magento\Framework\Code\Generator\Io + * @var Generator/Io */ protected $_ioObject; /** - * @var \Magento\Framework\Filesystem\Directory\Write + * @var Filesystem\Directory\Write + */ + private $generatedDirectory; + + /** + * @var Filesystem\Directory\Read + */ + private $logDirectory; + + /** + * @var string */ - protected $varDirectory; + private $testRelativePath = './Magento/Framework/Code/GeneratorTest/'; + /** + * @inheritdoc + */ protected function setUp() { - $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $this->varDirectory = $objectManager->get( - \Magento\Framework\Filesystem::class - )->getDirectoryWrite( - DirectoryList::VAR_DIR - ); - $generationDirectory = $this->varDirectory->getAbsolutePath('generation'); - $this->_ioObject = new \Magento\Framework\Code\Generator\Io( - new \Magento\Framework\Filesystem\Driver\File(), - $generationDirectory - ); + $objectManager = Bootstrap::getObjectManager(); + /** @var Filesystem $filesystem */ + $filesystem = $objectManager->get(Filesystem::class); + $this->generatedDirectory = $filesystem->getDirectoryWrite(DirectoryList::GENERATED_CODE); + $this->logDirectory = $filesystem->getDirectoryRead(DirectoryList::LOG); + $generatedDirectoryAbsolutePath = $this->generatedDirectory->getAbsolutePath(); + $this->_ioObject = new Generator\Io(new Filesystem\Driver\File(), $generatedDirectoryAbsolutePath); $this->_generator = $objectManager->create( - \Magento\Framework\Code\Generator::class, + Generator::class, [ 'ioObject' => $this->_ioObject, 'generatedEntities' => [ ExtensionAttributesInterfaceFactoryGenerator::ENTITY_TYPE => ExtensionAttributesInterfaceFactoryGenerator::class, - DIGenerator\Factory::ENTITY_TYPE => \Magento\Framework\ObjectManager\Code\Generator\Factory::class, - DIGenerator\Proxy::ENTITY_TYPE => \Magento\Framework\ObjectManager\Code\Generator\Proxy::class, - InterceptionGenerator\Interceptor::ENTITY_TYPE => - \Magento\Framework\Interception\Code\Generator\Interceptor::class, + DIGenerator\Factory::ENTITY_TYPE => DIGenerator\Factory::class, + DIGenerator\Proxy::ENTITY_TYPE => DIGenerator\Proxy::class, + InterceptionGenerator\Interceptor::ENTITY_TYPE => InterceptionGenerator\Interceptor::class, ] ] ); $this->_generator->setObjectManager($objectManager); } + /** + * @inheritdoc + */ protected function tearDown() { - $this->varDirectory->delete('generation'); $this->_generator = null; + if ($this->generatedDirectory->isExist($this->testRelativePath)) { + if (!$this->generatedDirectory->isWritable($this->testRelativePath)) { + $this->generatedDirectory->changePermissionsRecursively($this->testRelativePath, 0775, 0664); + } + $this->generatedDirectory->delete($this->testRelativePath); + } } protected function _clearDocBlock($classBody) @@ -79,81 +97,59 @@ protected function _clearDocBlock($classBody) return preg_replace('/(\/\*[\w\W]*)\nclass/', 'class', $classBody); } + /** + * Generates a new file with Factory class and compares with the sample from the + * SourceClassWithNamespaceFactory.php.sample file. + */ public function testGenerateClassFactoryWithNamespace() { $factoryClassName = self::CLASS_NAME_WITH_NAMESPACE . 'Factory'; - $result = false; - $generatorResult = $this->_generator->generateClass($factoryClassName); - if (\Magento\Framework\Code\Generator::GENERATION_ERROR !== $generatorResult) { - $result = true; - } - $this->assertTrue($result, 'Failed asserting that \'' . (string)$generatorResult . '\' equals \'success\'.'); - - $factory = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create($factoryClassName); - - $object = $factory->create(); - $this->assertInstanceOf(self::CLASS_NAME_WITH_NAMESPACE, $object); - - // This test is only valid if the factory created the object if Autoloader did not pick it up automatically - if (\Magento\Framework\Code\Generator::GENERATION_SUCCESS == $generatorResult) { - $content = $this->_clearDocBlock( - file_get_contents( - $this->_ioObject->generateResultFileName(self::CLASS_NAME_WITH_NAMESPACE . 'Factory') - ) - ); - $expectedContent = $this->_clearDocBlock( - file_get_contents(__DIR__ . '/_expected/SourceClassWithNamespaceFactory.php.sample') - ); - $this->assertEquals($expectedContent, $content); - } + $this->assertEquals(Generator::GENERATION_SUCCESS, $this->_generator->generateClass($factoryClassName)); + $factory = Bootstrap::getObjectManager()->create($factoryClassName); + $this->assertInstanceOf(self::CLASS_NAME_WITH_NAMESPACE, $factory->create()); + $content = $this->_clearDocBlock( + file_get_contents($this->_ioObject->generateResultFileName($factoryClassName)) + ); + $expectedContent = $this->_clearDocBlock( + file_get_contents(__DIR__ . '/_expected/SourceClassWithNamespaceFactory.php.sample') + ); + $this->assertEquals($expectedContent, $content); } + /** + * Generates a new file with Proxy class and compares with the sample from the + * SourceClassWithNamespaceProxy.php.sample file. + */ public function testGenerateClassProxyWithNamespace() { $proxyClassName = self::CLASS_NAME_WITH_NAMESPACE . '\Proxy'; - $result = false; - $generatorResult = $this->_generator->generateClass($proxyClassName); - if (\Magento\Framework\Code\Generator::GENERATION_ERROR !== $generatorResult) { - $result = true; - } - $this->assertTrue($result, 'Failed asserting that \'' . (string)$generatorResult . '\' equals \'success\'.'); - - $proxy = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create($proxyClassName); + $this->assertEquals(Generator::GENERATION_SUCCESS, $this->_generator->generateClass($proxyClassName)); + $proxy = Bootstrap::getObjectManager()->create($proxyClassName); $this->assertInstanceOf(self::CLASS_NAME_WITH_NAMESPACE, $proxy); - - // This test is only valid if the factory created the object if Autoloader did not pick it up automatically - if (\Magento\Framework\Code\Generator::GENERATION_SUCCESS == $generatorResult) { - $content = $this->_clearDocBlock( - file_get_contents($this->_ioObject->generateResultFileName(self::CLASS_NAME_WITH_NAMESPACE . '\Proxy')) - ); - $expectedContent = $this->_clearDocBlock( - file_get_contents(__DIR__ . '/_expected/SourceClassWithNamespaceProxy.php.sample') - ); - $this->assertEquals($expectedContent, $content); - } + $content = $this->_clearDocBlock( + file_get_contents($this->_ioObject->generateResultFileName($proxyClassName)) + ); + $expectedContent = $this->_clearDocBlock( + file_get_contents(__DIR__ . '/_expected/SourceClassWithNamespaceProxy.php.sample') + ); + $this->assertEquals($expectedContent, $content); } + /** + * Generates a new file with Interceptor class and compares with the sample from the + * SourceClassWithNamespaceInterceptor.php.sample file. + */ public function testGenerateClassInterceptorWithNamespace() { $interceptorClassName = self::CLASS_NAME_WITH_NAMESPACE . '\Interceptor'; - $result = false; - $generatorResult = $this->_generator->generateClass($interceptorClassName); - if (\Magento\Framework\Code\Generator::GENERATION_ERROR !== $generatorResult) { - $result = true; - } - $this->assertTrue($result, 'Failed asserting that \'' . (string)$generatorResult . '\' equals \'success\'.'); - - if (\Magento\Framework\Code\Generator::GENERATION_SUCCESS == $generatorResult) { - $content = $this->_clearDocBlock( - file_get_contents( - $this->_ioObject->generateResultFileName(self::CLASS_NAME_WITH_NAMESPACE . '\Interceptor') - ) - ); - $expectedContent = $this->_clearDocBlock( - file_get_contents(__DIR__ . '/_expected/SourceClassWithNamespaceInterceptor.php.sample') - ); - $this->assertEquals($expectedContent, $content); - } + $this->assertEquals(Generator::GENERATION_SUCCESS, $this->_generator->generateClass($interceptorClassName)); + $content = $this->_clearDocBlock( + file_get_contents($this->_ioObject->generateResultFileName($interceptorClassName)) + ); + $expectedContent = $this->_clearDocBlock( + file_get_contents(__DIR__ . '/_expected/SourceClassWithNamespaceInterceptor.php.sample') + ); + $this->assertEquals($expectedContent, $content); } /** @@ -163,26 +159,35 @@ public function testGenerateClassInterceptorWithNamespace() public function testGenerateClassExtensionAttributesInterfaceFactoryWithNamespace() { $factoryClassName = self::CLASS_NAME_WITH_NAMESPACE . 'ExtensionInterfaceFactory'; - $this->varDirectory->create( - $this->varDirectory->getAbsolutePath('generation') . '/Magento/Framework/Code/GeneratorTest/' - ); - - $generatorResult = $this->_generator->generateClass($factoryClassName); - + $this->generatedDirectory->create($this->testRelativePath); + $this->assertEquals(Generator::GENERATION_SUCCESS, $this->_generator->generateClass($factoryClassName)); $factory = Bootstrap::getObjectManager()->create($factoryClassName); - $object = $factory->create(); - - $this->assertEquals($generatorResult, Generator::GENERATION_SUCCESS); - $this->assertInstanceOf(self::CLASS_NAME_WITH_NAMESPACE . 'Extension', $object); - + $this->assertInstanceOf(self::CLASS_NAME_WITH_NAMESPACE . 'Extension', $factory->create()); $content = $this->_clearDocBlock( - file_get_contents( - $this->_ioObject->generateResultFileName(self::CLASS_NAME_WITH_NAMESPACE . 'ExtensionInterfaceFactory') - ) + file_get_contents($this->_ioObject->generateResultFileName($factoryClassName)) ); $expectedContent = $this->_clearDocBlock( file_get_contents(__DIR__ . '/_expected/SourceClassWithNamespaceExtensionInterfaceFactory.php.sample') ); $this->assertEquals($expectedContent, $content); } + + /** + * It tries to generate a new class file when the generated directory is read-only + */ + public function testGeneratorClassWithErrorSaveClassFile() + { + $factoryClassName = self::CLASS_NAME_WITH_NAMESPACE . 'Factory'; + $msgPart = 'Class ' . $factoryClassName . ' generation error: The requested class did not generate properly, ' + . 'because the \'generated\' directory permission is read-only.'; + $regexpMsgPart = preg_quote($msgPart); + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessageRegExp("/.*$regexpMsgPart.*/"); + $this->generatedDirectory->create($this->testRelativePath); + $this->generatedDirectory->changePermissionsRecursively($this->testRelativePath, 0555, 0444); + $generatorResult = $this->_generator->generateClass($factoryClassName); + $this->assertFalse($generatorResult); + $pathToSystemLog = $this->logDirectory->getAbsolutePath('system.log'); + $this->assertContains($msgPart, file_get_contents($pathToSystemLog)); + } } diff --git a/lib/internal/Magento/Framework/Code/Generator.php b/lib/internal/Magento/Framework/Code/Generator.php index 0b807775e032a..20b226aa8283a 100644 --- a/lib/internal/Magento/Framework/Code/Generator.php +++ b/lib/internal/Magento/Framework/Code/Generator.php @@ -7,6 +7,11 @@ use Magento\Framework\Code\Generator\DefinedClasses; use Magento\Framework\Code\Generator\EntityAbstract; +use Magento\Framework\Code\Generator\Io; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Phrase; +use Magento\Framework\Filesystem\Driver\File; +use Psr\Log\LoggerInterface; class Generator { @@ -17,7 +22,7 @@ class Generator const GENERATION_SKIP = 'skip'; /** - * @var \Magento\Framework\Code\Generator\Io + * @var Io */ protected $_ioObject; @@ -32,26 +37,33 @@ class Generator protected $definedClasses; /** - * @var \Magento\Framework\ObjectManagerInterface + * @var ObjectManagerInterface */ protected $objectManager; /** - * @param Generator\Io $ioObject - * @param array $generatedEntities + * Logger instance + * + * @var LoggerInterface + */ + private $logger; + + /** + * @param Generator\Io $ioObject + * @param array $generatedEntities * @param DefinedClasses $definedClasses + * @param LoggerInterface $logger */ public function __construct( - \Magento\Framework\Code\Generator\Io $ioObject = null, + Io $ioObject = null, array $generatedEntities = [], - DefinedClasses $definedClasses = null + DefinedClasses $definedClasses = null, + LoggerInterface $logger = null ) { - $this->_ioObject = $ioObject - ?: new \Magento\Framework\Code\Generator\Io( - new \Magento\Framework\Filesystem\Driver\File() - ); + $this->_ioObject = $ioObject ?: new Io(new File()); $this->definedClasses = $definedClasses ?: new DefinedClasses(); $this->_generatedEntities = $generatedEntities; + $this->logger = $logger; } /** @@ -111,8 +123,16 @@ public function generateClass($className) if ($generator !== null) { $this->tryToLoadSourceClass($className, $generator); if (!($file = $generator->generate())) { + /** @var $logger LoggerInterface */ $errors = $generator->getErrors(); - throw new \RuntimeException(implode(' ', $errors) . ' in [' . $className . ']'); + $errors[] = 'Class ' . $className . ' generation error: The requested class did not generate properly, ' + . 'because the \'generated\' directory permission is read-only. ' + . 'If --- after running the \'bin/magento setup:di:compile\' CLI command when the \'generated\' ' + . 'directory permission is set to write --- the requested class did not generate properly, then ' + . 'you must add the generated class object to the signature of the related construct method, only.'; + $message = implode(PHP_EOL, $errors); + $this->getLogger()->critical($message); + throw new \RuntimeException($message); } if (!$this->definedClasses->isClassLoadableFromMemory($className)) { $this->_ioObject->includeFile($file); @@ -121,13 +141,26 @@ public function generateClass($className) } } + /** + * Retrieve logger + * + * @return LoggerInterface + */ + private function getLogger() + { + if (!$this->logger) { + $this->logger = $this->getObjectManager()->get(LoggerInterface::class); + } + return $this->logger; + } + /** * Create entity generator * * @param string $generatorClass * @param string $entityName * @param string $className - * @return \Magento\Framework\Code\Generator\EntityAbstract + * @return EntityAbstract */ protected function createGeneratorInstance($generatorClass, $entityName, $className) { @@ -140,10 +173,10 @@ protected function createGeneratorInstance($generatorClass, $entityName, $classN /** * Set object manager instance. * - * @param \Magento\Framework\ObjectManagerInterface $objectManager + * @param ObjectManagerInterface $objectManager * @return $this */ - public function setObjectManager(\Magento\Framework\ObjectManagerInterface $objectManager) + public function setObjectManager(ObjectManagerInterface $objectManager) { $this->objectManager = $objectManager; return $this; @@ -152,11 +185,11 @@ public function setObjectManager(\Magento\Framework\ObjectManagerInterface $obje /** * Get object manager instance. * - * @return \Magento\Framework\ObjectManagerInterface + * @return ObjectManagerInterface */ public function getObjectManager() { - if (!($this->objectManager instanceof \Magento\Framework\ObjectManagerInterface)) { + if (!($this->objectManager instanceof ObjectManagerInterface)) { throw new \LogicException( "Object manager was expected to be set using setObjectManger() " . "before getObjectManager() invocation." @@ -169,7 +202,7 @@ public function getObjectManager() * Try to load/generate source class to check if it is valid or not. * * @param string $className - * @param \Magento\Framework\Code\Generator\EntityAbstract $generator + * @param EntityAbstract $generator * @return void * @throws \RuntimeException */ @@ -178,7 +211,7 @@ protected function tryToLoadSourceClass($className, $generator) $sourceClassName = $generator->getSourceClassName(); if (!$this->definedClasses->isClassLoadable($sourceClassName)) { if ($this->generateClass($sourceClassName) !== self::GENERATION_SUCCESS) { - $phrase = new \Magento\Framework\Phrase( + $phrase = new Phrase( 'Source class "%1" for "%2" generation does not exist.', [$sourceClassName, $className] ); diff --git a/lib/internal/Magento/Framework/Code/Test/Unit/GeneratorTest.php b/lib/internal/Magento/Framework/Code/Test/Unit/GeneratorTest.php index c175c0fe9be85..b6a4e545fea32 100644 --- a/lib/internal/Magento/Framework/Code/Test/Unit/GeneratorTest.php +++ b/lib/internal/Magento/Framework/Code/Test/Unit/GeneratorTest.php @@ -3,14 +3,22 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Framework\Code\Test\Unit; use Magento\Framework\Code\Generator; use Magento\Framework\Code\Generator\DefinedClasses; use Magento\Framework\Code\Generator\Io; - -class GeneratorTest extends \PHPUnit\Framework\TestCase +use Psr\Log\LoggerInterface; +use Magento\Framework\ObjectManager\Code\Generator\Factory; +use Magento\Framework\ObjectManager\Code\Generator\Proxy; +use Magento\Framework\Interception\Code\Generator\Interceptor; +use PHPUnit_Framework_MockObject_MockObject as Mock; +use PHPUnit\Framework\TestCase; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Code\Generator\EntityAbstract; +use Magento\GeneratedClass\Factory as GeneratedClassFactory; + +class GeneratorTest extends TestCase { /** * Class name parameter value @@ -22,45 +30,57 @@ class GeneratorTest extends \PHPUnit\Framework\TestCase * * @var array */ - protected $expectedEntities = [ - 'factory' => \Magento\Framework\ObjectManager\Code\Generator\Factory::ENTITY_TYPE, - 'proxy' => \Magento\Framework\ObjectManager\Code\Generator\Proxy::ENTITY_TYPE, - 'interceptor' => \Magento\Framework\Interception\Code\Generator\Interceptor::ENTITY_TYPE, + private $expectedEntities = [ + 'factory' => Factory::ENTITY_TYPE, + 'proxy' => Proxy::ENTITY_TYPE, + 'interceptor' => Interceptor::ENTITY_TYPE, ]; /** * System under test * - * @var \Magento\Framework\Code\Generator + * @var Generator */ - protected $model; + private $model; - /** @var \PHPUnit_Framework_MockObject_MockObject|Io */ - protected $ioObjectMock; + /** + * @var Io|Mock + */ + private $ioObjectMock; - /** @var \Magento\Framework\Code\Generator\DefinedClasses | \PHPUnit_Framework_MockObject_MockObject */ - protected $definedClassesMock; + /** + * @var DefinedClasses|Mock + */ + private $definedClassesMock; + + /** + * @var LoggerInterface|Mock + */ + private $loggerMock; protected function setUp() { - $this->definedClassesMock = $this->createMock(\Magento\Framework\Code\Generator\DefinedClasses::class); - $this->ioObjectMock = $this->getMockBuilder(\Magento\Framework\Code\Generator\Io::class) + $this->definedClassesMock = $this->createMock(DefinedClasses::class); + $this->ioObjectMock = $this->getMockBuilder(Io::class) ->disableOriginalConstructor() ->getMock(); - $this->model = $this->buildModel( + $this->loggerMock = $this->getMockForAbstractClass(LoggerInterface::class); + + $this->model = new Generator( $this->ioObjectMock, [ - 'factory' => \Magento\Framework\ObjectManager\Code\Generator\Factory::class, - 'proxy' => \Magento\Framework\ObjectManager\Code\Generator\Proxy::class, - 'interceptor' => \Magento\Framework\Interception\Code\Generator\Interceptor::class + 'factory' => Factory::class, + 'proxy' => Proxy::class, + 'interceptor' => Interceptor::class, ], - $this->definedClassesMock + $this->definedClassesMock, + $this->loggerMock ); } public function testGetGeneratedEntities() { - $this->model = $this->buildModel( + $this->model = new Generator( $this->ioObjectMock, ['factory', 'proxy', 'interceptor'], $this->definedClassesMock @@ -69,14 +89,16 @@ public function testGetGeneratedEntities() } /** + * @param string $className + * @param string $entityType * @expectedException \RuntimeException * @dataProvider generateValidClassDataProvider */ public function testGenerateClass($className, $entityType) { - $objectManagerMock = $this->createMock(\Magento\Framework\ObjectManagerInterface::class); + $objectManagerMock = $this->createMock(ObjectManagerInterface::class); $fullClassName = $className . $entityType; - $entityGeneratorMock = $this->getMockBuilder(\Magento\Framework\Code\Generator\EntityAbstract::class) + $entityGeneratorMock = $this->getMockBuilder(EntityAbstract::class) ->disableOriginalConstructor() ->getMock(); $objectManagerMock->expects($this->once())->method('create')->willReturn($entityGeneratorMock); @@ -87,7 +109,7 @@ public function testGenerateClass($className, $entityType) public function testGenerateClassWithWrongName() { $this->assertEquals( - \Magento\Framework\Code\Generator::GENERATION_ERROR, + Generator::GENERATION_ERROR, $this->model->generateClass(self::SOURCE_CLASS) ); } @@ -95,12 +117,12 @@ public function testGenerateClassWithWrongName() /** * @expectedException \RuntimeException */ - public function testGenerateClassWithError() + public function testGenerateClassWhenClassIsNotGenerationSuccess() { $expectedEntities = array_values($this->expectedEntities); $resultClassName = self::SOURCE_CLASS . ucfirst(array_shift($expectedEntities)); - $objectManagerMock = $this->createMock(\Magento\Framework\ObjectManagerInterface::class); - $entityGeneratorMock = $this->getMockBuilder(\Magento\Framework\Code\Generator\EntityAbstract::class) + $objectManagerMock = $this->createMock(ObjectManagerInterface::class); + $entityGeneratorMock = $this->getMockBuilder(EntityAbstract::class) ->disableOriginalConstructor() ->getMock(); $objectManagerMock->expects($this->once())->method('create')->willReturn($entityGeneratorMock); @@ -108,6 +130,57 @@ public function testGenerateClassWithError() $this->model->generateClass($resultClassName); } + /** + * @inheritdoc + */ + public function testGenerateClassWithErrors() + { + $expectedEntities = array_values($this->expectedEntities); + $resultClassName = self::SOURCE_CLASS . ucfirst(array_shift($expectedEntities)); + $errorMessages = [ + 'Error message 0', + 'Error message 1', + 'Error message 2', + ]; + $mainErrorMessage = 'Class ' . $resultClassName . ' generation error: The requested class did not generate ' + . 'properly, because the \'generated\' directory permission is read-only. ' + . 'If --- after running the \'bin/magento setup:di:compile\' CLI command when the \'generated\' ' + . 'directory permission is set to write --- the requested class did not generate properly, then ' + . 'you must add the generated class object to the signature of the related construct method, only.'; + $FinalErrorMessage = implode(PHP_EOL, $errorMessages) . "\n" . $mainErrorMessage; + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage($FinalErrorMessage); + + /** @var ObjectManagerInterface|Mock $objectManagerMock */ + $objectManagerMock = $this->createMock(ObjectManagerInterface::class); + /** @var EntityAbstract|Mock $entityGeneratorMock */ + $entityGeneratorMock = $this->getMockBuilder(EntityAbstract::class) + ->disableOriginalConstructor() + ->getMock(); + + $objectManagerMock->expects($this->once()) + ->method('create') + ->willReturn($entityGeneratorMock); + $entityGeneratorMock->expects($this->once()) + ->method('getSourceClassName') + ->willReturn(self::SOURCE_CLASS); + $this->definedClassesMock->expects($this->once()) + ->method('isClassLoadable') + ->with(self::SOURCE_CLASS) + ->willReturn(true); + $entityGeneratorMock->expects($this->once()) + ->method('generate') + ->willReturn(false); + $entityGeneratorMock->expects($this->once()) + ->method('getErrors') + ->willReturn($errorMessages); + $this->loggerMock->expects($this->once()) + ->method('critical') + ->with($FinalErrorMessage); + $this->model->setObjectManager($objectManagerMock); + $this->model->generateClass($resultClassName); + } + /** * @dataProvider trueFalseDataProvider */ @@ -124,14 +197,11 @@ public function testGenerateClassWithExistName($fileExists) $this->ioObjectMock->expects($this->exactly($includeFileInvokeCount))->method('includeFile'); $this->assertEquals( - \Magento\Framework\Code\Generator::GENERATION_SKIP, - $this->model->generateClass(\Magento\GeneratedClass\Factory::class) + Generator::GENERATION_SKIP, + $this->model->generateClass(GeneratedClassFactory::class) ); } - /** - * @return array - */ public function trueFalseDataProvider() { return [[true], [false]]; @@ -154,17 +224,4 @@ public function generateValidClassDataProvider() } return $data; } - - /** - * Build SUT object - * - * @param Io $ioObject - * @param array $generatedEntities - * @param DefinedClasses $definedClasses - * @return Generator - */ - private function buildModel(Io $ioObject, array $generatedEntities, DefinedClasses $definedClasses) - { - return new Generator($ioObject, $generatedEntities, $definedClasses); - } }