diff --git a/autoload/functions_oxDIC.php b/autoload/functions_oxDIC.php
index 1631be6..701fa17 100644
--- a/autoload/functions_oxDIC.php
+++ b/autoload/functions_oxDIC.php
@@ -33,7 +33,9 @@ function d3GetOxidDIC(): Container
{
try {
return d3GetOxidDIC_withExceptions();
+ // @codeCoverageIgnoreStart
} catch (d3DicException $exception) {
trigger_error($exception->getMessage(), E_USER_ERROR);
}
+ // @codeCoverageIgnoreEnd
}
diff --git a/composer.json b/composer.json
index c2ed5a2..2b065f4 100644
--- a/composer.json
+++ b/composer.json
@@ -30,7 +30,8 @@
"phpunit/phpunit": "^9.6",
"friendsofphp/php-cs-fixer": "~3.13.0",
"phpstan/phpstan": "^1.10",
- "rector/rector": "^0.18.13"
+ "rector/rector": "^0.18.13",
+ "mikey179/vfsstream": "^1.6.8"
},
"autoload": {
"psr-4": {
diff --git a/d3DicHandler.php b/d3DicHandler.php
index 66b7646..e961abc 100644
--- a/d3DicHandler.php
+++ b/d3DicHandler.php
@@ -40,24 +40,7 @@ class d3DicHandler implements d3DicHandlerInterface
*/
public static function getInstance(): Container
{
- try {
- $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
- $caller = $trace[1];
- $functionName = $caller['function'];
-
- if (in_array(strtolower($functionName), array_map('strtolower', self::$circularReferenceMethodNames))) {
- throw oxNew(Exception::class, 'method ' . $functionName . " can't use DIC due the danger of circular reference");
- }
-
- if (null == self::$_instance) {
- $oDicHandler = oxNew(d3DicHandler::class);
- self::$_instance = $oDicHandler->buildContainer();
- }
- } catch (Exception $exception) {
- throw new d3DicException($exception);
- }
-
- return self::$_instance;
+ return oxNew(d3DicHandler::class)->createInstance();
}
/**
@@ -66,17 +49,25 @@ class d3DicHandler implements d3DicHandlerInterface
*/
public static function getUncompiledInstance(): Container
{
- try {
- $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
- $caller = $trace[1];
- $functionName = $caller['function'];
+ return oxNew(d3DicHandler::class)->createInstance(false);
+ }
+ public static function removeInstance(): void
+ {
+ self::$_instance = null;
+ }
+
+ public function createInstance(bool $compiled = true): Container
+ {
+ try {
+ $functionName = $this->getFunctionNameFromTrace();
if (in_array(strtolower($functionName), array_map('strtolower', self::$circularReferenceMethodNames))) {
- throw oxNew(Exception::class, 'method '.$functionName." can't use DIC due the danger of circular reference");
+ throw oxNew(Exception::class, 'method ' . $functionName . " can't use DIC due the danger of circular reference");
}
- $oDicHandler = oxNew(d3DicHandler::class);
- self::$_instance = $oDicHandler->buildContainer(false);
+ if (null == self::$_instance) {
+ self::$_instance = $this->buildContainer($compiled);
+ }
} catch (Exception $exception) {
throw new d3DicException($exception);
}
@@ -84,9 +75,11 @@ class d3DicHandler implements d3DicHandlerInterface
return self::$_instance;
}
- public static function removeInstance(): void
+ protected function getFunctionNameFromTrace()
{
- self::$_instance = null;
+ $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
+ $caller = $trace[1];
+ return $caller['function'];
}
public function d3GetConfig(): Config
@@ -135,11 +128,6 @@ class d3DicHandler implements d3DicHandlerInterface
}
}
- protected function isNotInTest(): bool
- {
- return false == defined('OXID_PHP_UNIT') || true == defined('D3_MODCFG_TEST');
- }
-
protected function cacheFileExists(): bool
{
return file_exists($this->d3GetCacheFilePath());
@@ -162,11 +150,8 @@ class d3DicHandler implements d3DicHandlerInterface
if ($compileAndDump) {
$container->compile();
-
- if ($this->isNotInTest()) {
- $dumper = new PhpDumper($container);
- file_put_contents($this->d3GetCacheFilePath(), $dumper->dump(['class' => 'd3DIContainerCache']));
- }
+ $dumper = $this->getPhpDumper($container);
+ file_put_contents($this->d3GetCacheFilePath(), $dumper->dump(['class' => 'd3DIContainerCache']));
}
}
@@ -181,7 +166,6 @@ class d3DicHandler implements d3DicHandlerInterface
return $config->isProductiveMode()
&& !$config->getConfigParam('iDebug')
- && $this->isNotInTest()
&& $this->cacheFileExists();
}
@@ -190,13 +174,8 @@ class d3DicHandler implements d3DicHandlerInterface
return oxNew(ContainerBuilder::class);
}
- public function __clone()
+ public function getPhpDumper(ContainerBuilder $containerBuilder): PhpDumper
{
- /** keep clear */
- }
-
- public function __construct()
- {
- /** keep clear */
+ return new PhpDumper( $containerBuilder);
}
}
diff --git a/tests/phpunit.xml b/tests/phpunit.xml
index f8f7b77..d2f8dce 100644
--- a/tests/phpunit.xml
+++ b/tests/phpunit.xml
@@ -19,6 +19,11 @@
../
+
+ ./
+ ../rector.php
+ ../.php-cs-fixer.php
+
diff --git a/tests/unit/autoload/functions_oxDICTest.php b/tests/unit/autoload/functions_oxDICTest.php
index eb11539..490a105 100644
--- a/tests/unit/autoload/functions_oxDICTest.php
+++ b/tests/unit/autoload/functions_oxDICTest.php
@@ -28,6 +28,7 @@ class functions_oxDICTest extends TestCase
/**
* @test
* @throws Exception
+ * @covers ::d3GetOxidDIC_withExceptions()
*/
public function d3GetOxidDIC_withExceptionsTest(): void
{
@@ -42,6 +43,7 @@ class functions_oxDICTest extends TestCase
/**
* @test
* @throws Exception
+ * @covers ::d3GetOxidDIC()
*/
public function d3GetOxidDICTest(): void
{
diff --git a/tests/unit/d3DicExceptionTest.php b/tests/unit/d3DicExceptionTest.php
new file mode 100644
index 0000000..a4a4e0b
--- /dev/null
+++ b/tests/unit/d3DicExceptionTest.php
@@ -0,0 +1,50 @@
+
+ * @link https://www.oxidmodule.com
+ */
+
+declare(strict_types=1);
+
+namespace D3\DIContainerHandler\tests;
+
+use D3\DIContainerHandler\d3DicException;
+use InvalidArgumentException;
+use PHPUnit\Framework\TestCase;
+
+class d3DicExceptionTest extends TestCase
+{
+ /**
+ * @test
+ * @return void
+ * @covers \D3\DIContainerHandler\d3DicException::__construct
+ */
+ public function canConstruct()
+ {
+ $previousMessage = 'previousMessage';
+ $previousCode = 123;
+ $previous = new InvalidArgumentException($previousMessage, $previousCode);
+
+ $exception = new d3DicException($previous);
+
+ $this->assertSame(
+ $previous,
+ $exception->getPrevious()
+ );
+ $this->assertSame(
+ $previousMessage,
+ $exception->getMessage()
+ );
+ $this->assertSame(
+ $previousCode,
+ $exception->getCode()
+ );
+ }
+}
\ No newline at end of file
diff --git a/tests/unit/d3DicHandlerTest.php b/tests/unit/d3DicHandlerTest.php
index 4c39d1c..04819fa 100644
--- a/tests/unit/d3DicHandlerTest.php
+++ b/tests/unit/d3DicHandlerTest.php
@@ -15,23 +15,33 @@ declare(strict_types=1);
namespace D3\DIContainerHandler\tests;
+use D3\DIContainerHandler\d3DicException;
use D3\DIContainerHandler\d3DicHandler;
use D3\TestingTools\Development\CanAccessRestricted;
use d3DIContainerCache;
+use Exception;
use Generator;
+use org\bovigo\vfs\vfsStream;
use OxidEsales\Eshop\Core\Config;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use ReflectionException;
+use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
-define('D3_MODCFG_TEST', true);
-
class d3DicHandlerTest extends TestCase
{
use CanAccessRestricted;
+ public function setUp(): void
+ {
+ parent::setUp();
+
+ d3DicHandler::removeInstance();
+ }
+
/**
* @test
* @throws ReflectionException
@@ -118,6 +128,65 @@ class d3DicHandlerTest extends TestCase
);
}
+ /**
+ * @test
+ * @param bool $throwException
+ * @param bool $expectException
+ * @param string $circularReferenceMethod
+ *
+ * @return void
+ * @throws ReflectionException
+ * @covers \D3\DIContainerHandler\d3DicHandler::createInstance
+ * @dataProvider canCreateInstanceDataProvider
+ */
+ public function canCreateInstance(bool $throwException, bool $expectException, string $circularReferenceMethod = '')
+ {
+ /** @var d3DicHandler|MockObject $sut */
+ $sut = $this->getMockBuilder(d3DicHandler::class)
+ ->onlyMethods(['buildContainer', 'getFunctionNameFromTrace'])
+ ->getMock();
+ if ($throwException)
+ $sut->method( 'buildContainer' )->willThrowException( new Exception( 'fixture' ) );
+
+ $sut->method('getFunctionNameFromTrace')->willReturn($circularReferenceMethod);
+ if ($expectException)
+ $this->expectException(d3DicException::class);
+
+ $this->callMethod(
+ $sut,
+ 'createInstance'
+ );
+ }
+
+ public function canCreateInstanceDataProvider(): Generator
+ {
+ yield "don't throw exception" => [false, false];
+ yield "throw exception" => [true, true];
+ yield "has circular reference method name" => [false, true, 'getViewConfig'];
+ }
+
+ /**
+ * @test
+ * @return void
+ * @throws ReflectionException
+ * @covers \D3\DIContainerHandler\d3DicHandler::getFunctionNameFromTrace
+ */
+ public function canGetFunctionNameFromTrace()
+ {
+ /** @var d3DicHandler|MockObject $sut */
+ $sut = $this->getMockBuilder(d3DicHandler::class)
+ ->onlyMethods(get_class_methods(d3DicHandler::class))
+ ->getMock();
+
+ $this->assertSame(
+ 'invokeArgs',
+ $this->callMethod(
+ $sut,
+ 'getFunctionNameFromTrace'
+ )
+ );
+ }
+
/**
* @test
* @throws ReflectionException
@@ -225,23 +294,6 @@ class d3DicHandlerTest extends TestCase
);
}
- /**
- * @test
- * @throws ReflectionException
- * @covers \D3\DIContainerHandler\d3DicHandler::isNotInTest
- */
- public function isNotInTest(): void
- {
- $sut = new d3DicHandler();
-
- $this->assertTrue(
- $this->callMethod(
- $sut,
- 'isNotInTest'
- )
- );
- }
-
/**
* @test
* @throws ReflectionException
@@ -276,52 +328,102 @@ class d3DicHandlerTest extends TestCase
/**
* @test
+ * @param bool $useCacheContainer
+ * @param bool $compile
*
- *
+ * @return void
* @throws ReflectionException
* @dataProvider buildContainerTestDataProvider
* @covers \D3\DIContainerHandler\d3DicHandler::buildContainer
*/
- public function buildContainerTest(bool $productive, int $debug, bool $notInTest, bool $cacheFileExist, bool $cachedContainer): void
+ public function buildContainerTest(bool $useCacheContainer, bool $compile): void
{
- $cachedContainerMock = $this->getMockBuilder(d3DIContainerCache::class)
- ->getMock();
+ $structure = [
+ 'source_directory' => [],
+ ];
+ vfsStream::setup();
+ $fsRoot = vfsStream::create($structure);
$containerBuilderMock = $this->getMockBuilder(ContainerBuilder::class)->onlyMethods([ 'compile' ])->getMock();
- $containerBuilderMock->expects($this->exactly((int) ! $cachedContainer))->method('compile');
+ $containerBuilderMock->expects($this->exactly((int) (!$useCacheContainer && $compile)))->method('compile');
- $configMock = $this->getMockBuilder(Config::class)
- ->onlyMethods(['isProductiveMode', 'getConfigParam'])
+ /** @var PhpDumper|MockObject $phpDumperMock */
+ $phpDumperMock = $this->getMockBuilder(PhpDumper::class)
+ ->disableOriginalConstructor()
+ ->onlyMethods(get_class_methods(PhpDumper::class))
->getMock();
- $configMock->method('isProductiveMode')->willReturn($productive);
- $configMock->method('getConfigParam')->willReturnMap([['iDebug', $debug]]);
+ $phpDumperMock->expects($this->exactly((int) (!$useCacheContainer && $compile)))->method('dump');
+ /** @var d3DicHandler|MockObject $sut */
$sut = $this->getMockBuilder(d3DicHandler::class)
- ->onlyMethods(['d3GetConfig', 'd3GetCacheContainer', 'getContainerBuilder', 'isNotInTest', 'cacheFileExists'])
+ ->onlyMethods(['d3UseCachedContainer', 'd3GetCacheContainer', 'getContainerBuilder', 'd3GetCacheFilePath', 'getPhpDumper'])
->getMock();
- $sut->method('d3GetConfig')->willReturn($configMock);
- $sut->expects($this->exactly((int) $cachedContainer))->method('d3GetCacheContainer')->willReturn($cachedContainerMock);
- $sut->expects($this->exactly((int) !$cachedContainer))->method('getContainerBuilder')->willReturn($containerBuilderMock);
- $sut->method('isNotInTest')->willReturn($notInTest);
- $sut->method('cacheFileExists')->willReturn($cacheFileExist);
+ $sut->expects($this->once())->method('d3UseCachedContainer')->willReturn($useCacheContainer);
+ $sut->expects($this->exactly((int) $useCacheContainer))->method('d3GetCacheContainer');
+ $sut->expects($this->exactly((int) !$useCacheContainer))->method('getContainerBuilder')->willReturn($containerBuilderMock);
+ $sut->method('d3GetCacheFilePath')->willReturn($fsRoot->getChild('source_directory')->path().'/DIContainer.php');
+ $sut->method('getPhpDumper')->willReturn($phpDumperMock);
- $this->assertSame(
- $cachedContainer ? $cachedContainerMock : $containerBuilderMock,
+ $this->assertInstanceOf(
+ Container::class,
$this->callMethod(
$sut,
'buildContainer',
- ['false']
+ [$compile]
)
);
}
public function buildContainerTestDataProvider(): Generator
{
- yield 'notProductive' => [false, 0, false, true, false];
- yield 'debug' => [true, 1, false, true, false];
- yield 'inTest' => [true, 0, false, true, false];
- yield 'cacheFileNotExist' => [true, 0, false, false, false];
- yield 'cachedContainer' => [true, 0, true, true, true];
+ yield "can't use cached container, do compile" => [false, true];
+ yield "can't use cached container, don't compile" => [false, false];
+ yield "use cached container" => [true, false];
+ }
+
+ /**
+ * @test
+ * @param bool $productive
+ * @param int $debug
+ * @param bool $cacheFileExist
+ * @param bool $expected
+ *
+ * @return void
+ * @throws ReflectionException
+ * @covers \D3\DIContainerHandler\d3DicHandler::d3UseCachedContainer
+ * @dataProvider canUseCachedContainerDataProvider
+ */
+ public function canUseCachedContainerTest(bool $productive, int $debug, bool $cacheFileExist, bool $expected)
+ {
+ /** @var Config|MockObject $configMock */
+ $configMock = $this->getMockBuilder(Config::class)
+ ->onlyMethods(['isProductiveMode', 'getConfigParam'])
+ ->getMock();
+ $configMock->method('isProductiveMode')->willReturn($productive);
+ $configMock->method('getConfigParam')->willReturnMap([['iDebug', NULL, $debug]]);
+
+ /** @var d3DicHandler|MockObject $sut */
+ $sut = $this->getMockBuilder(d3DicHandler::class)
+ ->onlyMethods(['d3GetConfig', 'cacheFileExists'])
+ ->getMock();
+ $sut->method('d3GetConfig')->willReturn($configMock);
+ $sut->method('cacheFileExists')->willReturn($cacheFileExist);
+
+ $this->assertSame(
+ $expected,
+ $this->callMethod(
+ $sut,
+ 'd3UseCachedContainer'
+ )
+ );
+ }
+
+ public function canUseCachedContainerDataProvider(): Generator
+ {
+ yield "not productive" => [false, 0, true, false];
+ yield 'is debug' => [true, 1, true, false];
+ yield 'no cache file' => [true, 0, false, false];
+ yield 'can use cached' => [true, 0, true, true];
}
/**
@@ -341,4 +443,28 @@ class d3DicHandlerTest extends TestCase
)
);
}
+
+ /**
+ * @test
+ * @return void
+ * @throws ReflectionException
+ * @covers \D3\DIContainerHandler\d3DicHandler::getPhpDumper
+ */
+ public function canGetPhpDumper(): void
+ {
+ /** @var ContainerBuilder|MockObject $containerBuilderMock */
+ $containerBuilderMock = $this->getMockBuilder(ContainerBuilder::class)
+ ->onlyMethods(['isCompiled'])
+ ->getMock();
+ $containerBuilderMock->method('isCompiled')->willReturn(true);
+
+ $this->assertInstanceOf(
+ PhpDumper::class,
+ $this->callMethod(
+ new d3DicHandler(),
+ 'getPhpDumper',
+ [$containerBuilderMock]
+ )
+ );
+ }
}
diff --git a/tests/unit/d3DicUtilitiesTest.php b/tests/unit/d3DicUtilitiesTest.php
index 77492e4..a24b5b9 100644
--- a/tests/unit/d3DicUtilitiesTest.php
+++ b/tests/unit/d3DicUtilitiesTest.php
@@ -29,7 +29,9 @@ class d3DicUtilitiesTest extends TestCase
/**
* @test
*
+ * @param string $className
* @param string|null $additional
+ * @param string $expected
*
* @throws ReflectionException
* @covers \D3\DIContainerHandler\d3DicUtilities::getServiceId
diff --git a/tests/unit/definitionFileContainerTest.php b/tests/unit/definitionFileContainerTest.php
index 2d26b89..aa783b1 100644
--- a/tests/unit/definitionFileContainerTest.php
+++ b/tests/unit/definitionFileContainerTest.php
@@ -29,10 +29,10 @@ class definitionFileContainerTest extends TestCase
/**
* @test
*
- *
* @throws ReflectionException
* @dataProvider addDefinitionsTestDataProvider
* @covers \D3\DIContainerHandler\definitionFileContainer::addDefinitions
+ * @covers \D3\DIContainerHandler\definitionFileContainer::__construct
*/
public function addDefinitionsTest(string $file, string $type, int $sumand, bool $expectException): void
{