Skip to content

Commit 7ff0f2b

Browse files
committed
MAGETWO-67626: Auto-generated classes behave differently in unit tests and application
- refactored generators - skip generation of non-conventional classes/interfaces
1 parent 8cbb223 commit 7ff0f2b

File tree

6 files changed

+216
-33
lines changed

6 files changed

+216
-33
lines changed

dev/tests/unit/framework/autoload.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Magento\Framework\Code\Generator\Io;
99
use Magento\Framework\Filesystem\Driver\File;
1010
use Magento\Framework\TestFramework\Unit\Autoloader\ExtensionAttributesGenerator;
11+
use Magento\Framework\TestFramework\Unit\Autoloader\ExtensionAttributesInterfaceGenerator;
1112
use Magento\Framework\TestFramework\Unit\Autoloader\FactoryGenerator;
1213
use Magento\Framework\TestFramework\Unit\Autoloader\GeneratedClassesAutoloader;
1314

@@ -18,6 +19,7 @@
1819
$generatedCodeAutoloader = new GeneratedClassesAutoloader(
1920
[
2021
new ExtensionAttributesGenerator(),
22+
new ExtensionAttributesInterfaceGenerator(),
2123
new FactoryGenerator(),
2224
],
2325
$generatorIo
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Framework\TestFramework\Test\Unit\Autoloader;
8+
9+
use Magento\Framework\TestFramework\Unit\Autoloader\ExtensionAttributesGenerator;
10+
11+
class ExtensionAttributesGeneratorTest extends \PHPUnit_Framework_TestCase
12+
{
13+
/**
14+
* @var ExtensionAttributesGenerator
15+
*/
16+
private $subject;
17+
18+
protected function setUp()
19+
{
20+
$this->subject = new ExtensionAttributesGenerator();
21+
}
22+
23+
public function testGenerateExtensionAttributes()
24+
{
25+
$this->assertStringMatchesFormat(
26+
"%Anamespace My;%Aclass SimpleExtension implements SimpleExtensionInterface%A",
27+
$this->subject->generate('\My\SimpleExtension')
28+
);
29+
}
30+
31+
/**
32+
* @dataProvider generateNonExtensionAttributesDataProvider
33+
* @param string $className
34+
*/
35+
public function testGenerateNonExtensionAttributes($className)
36+
{
37+
$this->assertFalse($this->subject->generate($className));
38+
}
39+
40+
/**
41+
* @return array
42+
*/
43+
public function generateNonExtensionAttributesDataProvider()
44+
{
45+
return [
46+
'non-extension attribute class' => ['\My\SimpleClass'],
47+
'non-conventional extension attribute name' => ['\My\Extension'],
48+
];
49+
}
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Framework\TestFramework\Test\Unit\Autoloader;
8+
9+
use Magento\Framework\TestFramework\Unit\Autoloader\ExtensionAttributesInterfaceGenerator;
10+
11+
class ExtensionAttributesInterfaceGeneratorTest extends \PHPUnit_Framework_TestCase
12+
{
13+
/**
14+
* @var ExtensionAttributesInterfaceGenerator
15+
*/
16+
private $subject;
17+
18+
protected function setUp()
19+
{
20+
$this->subject = new ExtensionAttributesInterfaceGenerator();
21+
}
22+
23+
public function testGenerateExtensionAttributesInterface()
24+
{
25+
$this->assertStringMatchesFormat(
26+
"%Anamespace My;%Ainterface SimpleExtensionInterface extends "
27+
. "\\Magento\\Framework\\Api\\ExtensionAttributesInterface%A",
28+
$this->subject->generate('\My\SimpleExtensionInterface')
29+
);
30+
}
31+
32+
/**
33+
* @dataProvider generateNonExtensionAttributesInterfaceDataProvider
34+
* @param string $className
35+
*/
36+
public function testGenerateNonExtensionAttributesInterface($className)
37+
{
38+
$this->assertFalse($this->subject->generate($className));
39+
}
40+
41+
/**
42+
* @return array
43+
*/
44+
public function generateNonExtensionAttributesInterfaceDataProvider()
45+
{
46+
return [
47+
'non-extension attribute interface' => ['\My\SimpleInterface'],
48+
'non-conventional extension attribute interface name' => ['\My\ExtensionInterface'],
49+
];
50+
}
51+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Framework\TestFramework\Test\Unit\Autoloader;
8+
9+
use Magento\Framework\TestFramework\Unit\Autoloader\FactoryGenerator;
10+
11+
class FactoryGeneratorTest extends \PHPUnit_Framework_TestCase
12+
{
13+
/**
14+
* @var FactoryGenerator
15+
*/
16+
private $subject;
17+
18+
protected function setUp()
19+
{
20+
$this->subject = new FactoryGenerator();
21+
}
22+
23+
public function testGenerateFactory()
24+
{
25+
$this->assertStringMatchesFormat(
26+
'%Anamespace My%Aclass SimpleFactory%Afunction create%A',
27+
$this->subject->generate('\My\SimpleFactory')
28+
);
29+
}
30+
31+
/**
32+
* @dataProvider generateNonFactoryDataProvider
33+
* @param string $className
34+
*/
35+
public function testGenerateNonFactory($className)
36+
{
37+
$this->assertFalse($this->subject->generate($className));
38+
}
39+
40+
/**
41+
* @return array
42+
*/
43+
public function generateNonFactoryDataProvider()
44+
{
45+
return [
46+
'non-factory class' => ['\My\SimpleClass'],
47+
'non-conventional factory name' => ['\My\Factory'],
48+
];
49+
}
50+
}

lib/internal/Magento/Framework/TestFramework/Unit/Autoloader/ExtensionAttributesGenerator.php

Lines changed: 12 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66

77
namespace Magento\Framework\TestFramework\Unit\Autoloader;
88

9+
use Magento\Framework\Code\Generator\ClassGenerator;
10+
911
/**
10-
* Code generation for the undeclared *Extension and *ExtensionInterface types
12+
* Code generation for the undeclared *Extension types
1113
*
1214
* These files must be generated since they are referenced in many interfaces/classes and cannot be mocked easily.
1315
* For unit tests, these are just empty type definitions. You should use integration tests if you want to see the real
@@ -16,47 +18,23 @@
1618
class ExtensionAttributesGenerator implements GeneratorInterface
1719
{
1820
/**
19-
* Generates a stub class/interface for classes that follow the convention
21+
* Generates a stub class for classes that follow the convention
2022
*
21-
* The convention is "<SourceClass>ExtensionInterface" or "<SourceClass>Extension"
23+
* The convention is "<SourceClass>Extension"
2224
*
2325
* @param string $className
2426
* @return bool|string
2527
*/
2628
public function generate($className)
2729
{
28-
if (!$this->isExtension($className) && !$this->isExtensionInterface($className)) {
30+
if (!$this->isExtension($className)) {
2931
return false;
3032
}
31-
$classNameParts = explode('\\', $className);
32-
33-
/* Split the type name and namespace for the file's contents. */
34-
$justTypeName = $classNameParts[count($classNameParts) - 1];
35-
36-
unset($classNameParts[count($classNameParts) - 1]);
37-
$namespace = implode('\\', $classNameParts);
38-
39-
$content = false;
40-
if ($this->isExtension($className)) {
41-
$content = "namespace $namespace;\n\nclass $justTypeName implements "
42-
. "{$justTypeName}Interface\n{\n\n}";
43-
} elseif ($this->isExtensionInterface($className)) {
44-
$content = "namespace $namespace;\n\ninterface $justTypeName extends "
45-
. "\\Magento\\Framework\\Api\\ExtensionAttributesInterface \n{\n\n}";
46-
}
47-
return $content;
48-
}
33+
$classGenerator = new ClassGenerator();
34+
$classGenerator->setName($className)
35+
->setImplementedInterfaces(["{$className}Interface"]);
36+
return $classGenerator->generate();
4937

50-
/**
51-
* Determines if the passed in class name is an ExtensionInterface type.
52-
*
53-
* @param string $className
54-
* @return bool
55-
*/
56-
private function isExtensionInterface($className)
57-
{
58-
$suffix = "ExtensionInterface";
59-
return substr($className, -strlen($suffix), strlen($suffix)) === $suffix;
6038
}
6139

6240
/**
@@ -68,6 +46,7 @@ private function isExtensionInterface($className)
6846
private function isExtension($className)
6947
{
7048
$suffix = "Extension";
71-
return substr($className, -strlen($suffix), strlen($suffix)) === $suffix;
49+
$sourceName = rtrim(substr($className, 0, -strlen($suffix)), '\\');
50+
return $sourceName . $suffix == $className;
7251
}
7352
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Framework\TestFramework\Unit\Autoloader;
8+
9+
use Magento\Framework\Code\Generator\InterfaceGenerator;
10+
11+
/**
12+
* Code generation for the undeclared *ExtensionInterface
13+
*
14+
* These files must be generated since they are referenced in many interfaces/classes and cannot be mocked easily.
15+
* For unit tests, these are just empty type definitions. You should use integration tests if you want to see the real
16+
* types be generated with the properties from the extension attributes config.
17+
*/
18+
class ExtensionAttributesInterfaceGenerator implements GeneratorInterface
19+
{
20+
/**
21+
* Generates a stub interface for interfaces that follow the convention
22+
*
23+
* The convention is "<SourceClass>ExtensionInterface"
24+
*
25+
* @param string $className
26+
* @return bool|string
27+
*/
28+
public function generate($className)
29+
{
30+
if (!$this->isExtensionInterface($className)) {
31+
return false;
32+
}
33+
$interfaceGenerator = new InterfaceGenerator();
34+
$interfaceGenerator->setName($className)
35+
->setExtendedClass('\Magento\Framework\Api\ExtensionAttributesInterface');
36+
return $interfaceGenerator->generate();
37+
}
38+
39+
/**
40+
* Determines if the passed in class name is an ExtensionInterface type.
41+
*
42+
* @param string $className
43+
* @return bool
44+
*/
45+
private function isExtensionInterface($className)
46+
{
47+
$suffix = "ExtensionInterface";
48+
$sourceName = rtrim(substr($className, 0, -strlen($suffix)), '\\');
49+
return $sourceName . $suffix == $className;
50+
}
51+
}

0 commit comments

Comments
 (0)