diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 0000000..165765a --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1 @@ +.phpunit.result.cache diff --git a/tests/phpunit.xml b/tests/phpunit.xml new file mode 100644 index 0000000..f8f7b77 --- /dev/null +++ b/tests/phpunit.xml @@ -0,0 +1,28 @@ + + + + + ../ + + + + + unit/ + + + diff --git a/tests/unit/autoload/functions_oxDICTest.php b/tests/unit/autoload/functions_oxDICTest.php new file mode 100644 index 0000000..7f5b0eb --- /dev/null +++ b/tests/unit/autoload/functions_oxDICTest.php @@ -0,0 +1,124 @@ + + * @link https://www.oxidmodule.com + */ + +declare(strict_types=1); + +namespace D3\DIContainerHandler\tests\autoload; + +use PHPUnit\Framework\TestCase; +use ReflectionClass; +use ReflectionException; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +class functions_oxDICTest extends TestCase +{ + /** + * @test + * @return void + */ + public function d3GetOxidDICTest(): void + { + $this->assertInstanceOf( + ContainerBuilder::class, + d3GetOxidDIC() + ); + } + + /**************/ + + + + /** + * Calls a private or protected object method. + * + * @param object $object + * @param string $methodName + * @param array $arguments + * + * @return mixed + * @throws ReflectionException + */ + public function callMethod($object, $methodName, array $arguments = []) + { + $class = new ReflectionClass($object); + $method = $class->getMethod($methodName); + $method->setAccessible(true); + return $method->invokeArgs($object, $arguments); + } + + /** + * Sets a private or protected property in defined class instance + * + * @param object $object + * @param string $valueName + * @param mixed $value + * @throws ReflectionException + */ + public function setValue($object, $valueName, $value) + { + $reflection = new ReflectionClass($object); + $property = $reflection->getProperty($valueName); + $property->setAccessible(true); + $property->setValue($object, $value); + } + + /** + * Sets a private or protected property in mocked class instance based on original class + * (required for e.g. final properties, which aren't contained in mock, but in original class) + * @param $mockedClassName * FQNS of original class + * @param $object * mock object + * @param $valueName * property name + * @param $value * new property value + * + * @throws ReflectionException + */ + public function setMockedClassValue($mockedClassName, $object, $valueName, $value) + { + $property = new \ReflectionProperty($mockedClassName, $valueName); + $property->setAccessible(true); + $property->setValue($object, $value); + } + + /** + * get a private or protected property from defined class instance + * + * @param object $object + * @param string $valueName + * @param mixed $value + * @return mixed + * @throws ReflectionException + */ + public function getValue($object, $valueName) + { + $reflection = new ReflectionClass($object); + $property = $reflection->getProperty($valueName); + $property->setAccessible(true); + return $property->getValue($object); + } + + /** + * get a private or protected property from mocked class instance based on original class + * (required for e.g. final properties, which aren't contained in mock, but in original class) + * @param object $object + * @param string $valueName + * @param mixed $value + * @return mixed + * @throws ReflectionException + */ + public function getMockedClassValue($mockedClassName, $object, $valueName) + { + $property = new \ReflectionProperty($mockedClassName, $valueName); + $property->setAccessible(true); + return $property->getValue($object); + } +} \ No newline at end of file diff --git a/tests/unit/d3DicHandlerTest.php b/tests/unit/d3DicHandlerTest.php new file mode 100644 index 0000000..15cabdf --- /dev/null +++ b/tests/unit/d3DicHandlerTest.php @@ -0,0 +1,459 @@ + + * @link https://www.oxidmodule.com + */ + +declare(strict_types=1); + +namespace D3\DIContainerHandler\tests; + +use D3\DIContainerHandler\d3DicHandler; +use d3DIContainerCache; +use Generator; +use OxidEsales\Eshop\Core\Config; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; +use ReflectionClass; +use ReflectionException; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; + +define('D3_MODCFG_TEST', true); + +class d3DicHandlerTest extends TestCase +{ + /** + * @test + * @return void + * @throws ReflectionException + * @covers \D3\DIContainerHandler\d3DicHandler::getInstance + */ + public function getInstanceTest(): void + { + $sut = new d3DicHandler(); + + $this->setValue( + $sut, + '_instance', + null + ); + + $containerBuilder = $this->callMethod( + $sut, + 'getInstance' + ); + + $this->assertInstanceOf( + ContainerBuilder::class, + $containerBuilder + ); + + $this->assertSame( + $containerBuilder, + $this->callMethod( + $sut, + 'getInstance' + ) + ); + + $this->assertTrue($containerBuilder->isCompiled()); + } + + /** + * @test + * @return void + * @throws ReflectionException + * @covers \D3\DIContainerHandler\d3DicHandler::getUncompiledInstance + */ + public function getUncompiledInstanceTest(): void + { + $sut = new d3DicHandler(); + + $containerBuilder = $this->callMethod( + $sut, + 'getUncompiledInstance' + ); + + $this->assertInstanceOf( + ContainerBuilder::class, + $containerBuilder + ); + + $this->assertFalse($containerBuilder->isCompiled()); + } + + /** + * @test + * @return void + * @throws ReflectionException + * @covers \D3\DIContainerHandler\d3DicHandler::removeInstance + */ + public function removeInstanceTest(): void + { + $sut = new d3DicHandler(); + + $containerBuilder = $this->callMethod( + $sut, + 'getInstance' + ); + + $this->callMethod( + $sut, + 'removeInstance' + ); + + $this->assertNotSame( + $containerBuilder, + $this->callMethod( + $sut, + 'getInstance' + ) + ); + } + + /** + * @test + * @return void + * @throws ReflectionException + * @covers \D3\DIContainerHandler\d3DicHandler::d3GetConfig + */ + public function d3GetConfigTest(): void + { + $sut = new d3DicHandler(); + + $this->assertInstanceOf( + Config::class, + $this->callMethod( + $sut, + 'd3GetConfig' + ) + ); + } + + /** + * @test + * @return void + * @throws ReflectionException + * @covers \D3\DIContainerHandler\d3DicHandler::d3GetCacheFilePath + */ + public function d3GetCacheFilePathTest(): void + { + $sut = new d3DicHandler(); + + $this->assertMatchesRegularExpression( + '/.*?\/tmp\/.*?DicContainer_\d+\.php$/m', + $this->callMethod( + $sut, + 'd3GetCacheFilePath' + ) + ); + } + + /** + * @test + * @return void + * @throws ReflectionException + * @covers \D3\DIContainerHandler\d3DicHandler::d3GetCacheContainer + */ + public function d3GetCacheContainerTest(): void + { + $sut = new d3DicHandler(); + + $this->callMethod($sut, 'buildContainer'); + + $this->assertInstanceOf( + d3DIContainerCache::class, + $this->callMethod( + $sut, + 'd3GetCacheContainer' + ) + ); + } + + /** + * @test + * @return void + * @throws ReflectionException + * @covers \D3\DIContainerHandler\d3DicHandler::d3GetFileLoader + */ + public function d3GetFileLoaderTest(): void + { + $sut = new d3DicHandler(); + + $containerBuilderMock = $this->getMockBuilder(ContainerBuilder::class) + ->getMock(); + + $this->assertInstanceOf( + YamlFileLoader::class, + $this->callMethod( + $sut, + 'd3GetFileLoader', + [$containerBuilderMock] + ) + ); + } + + /** + * @test + * @return void + * @throws ReflectionException + * @covers \D3\DIContainerHandler\d3DicHandler::loadFiles + */ + public function loadFilesTest(): void + { + /** @var ContainerBuilder|MockObject $containerBuilderMock */ + $containerBuilderMock = $this->getMockBuilder(ContainerBuilder::class) + ->getMock(); + + /** @var YamlFileLoader|MockObject $fileLoaderMock */ + $fileLoaderMock = $this->getMockBuilder(YamlFileLoader::class) + ->disableOriginalConstructor() + ->onlyMethods(['load']) + ->getMock(); + $fileLoaderMock->expects($this->atLeastOnce())->method('load'); + + /** @var d3DicHandler|MockObject $sut */ + $sut = $this->getMockBuilder(d3DicHandler::class) + ->onlyMethods(['d3GetFileLoader']) + ->getMock(); + $sut->method('d3GetFileLoader')->willReturn($fileLoaderMock); + + $this->callMethod( + $sut, + 'loadFiles', + [$containerBuilderMock] + ); + } + + /** + * @test + * @return void + * @throws ReflectionException + * @covers \D3\DIContainerHandler\d3DicHandler::isNotInTest + */ + public function isNotInTest(): void + { + $sut = new d3DicHandler(); + + $this->assertTrue( + $this->callMethod( + $sut, + 'isNotInTest' + ) + ); + } + + /** + * @test + * @return void + * @throws ReflectionException + * @dataProvider cacheFileExistsTestDataProvider + * @covers \D3\DIContainerHandler\d3DicHandler::cacheFileExists + */ + public function cacheFileExistsTest($cacheExist) + { + /** @var d3DicHandler|MockObject $sut */ + if (!$cacheExist) { + $sut = $this->getMockBuilder(d3DicHandler::class) + ->onlyMethods(['d3GetCacheFilePath']) + ->getMock(); + $sut->method( 'd3GetCacheFilePath' )->willReturn( 'foo' ); + } else { + $sut = new d3DicHandler(); + } + + $this->assertSame( + $cacheExist, + $this->callMethod( + $sut, + 'cacheFileExists' + ) + ); + } + + /** + * @return Generator + */ + public function cacheFileExistsTestDataProvider(): Generator + { + yield 'cacheExist' => [true]; + yield 'cacheMissing'=> [false]; + } + + /** + * @test + * + * @param bool $productive + * @param int $debug + * @param bool $notInTest + * @param bool $cacheFileExist + * @param bool $cachedContainer + * + * @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 + { + $cachedContainerMock = $this->getMockBuilder(d3DIContainerCache::class) + ->getMock(); + + /** @var ContainerBuilder|MockObject $containerBuilderMock */ + $containerBuilderMock = $this->getMockBuilder( ContainerBuilder::class )->onlyMethods( [ 'compile' ] )->getMock(); + $containerBuilderMock->expects( $this->exactly( (int) ! $cachedContainer ) )->method( 'compile' ); + + /** @var Config|MockObject $configMock */ + $configMock = $this->getMockBuilder(Config::class) + ->onlyMethods(['isProductiveMode', 'getConfigParam']) + ->getMock(); + $configMock->method('isProductiveMode')->willReturn($productive); + $configMock->method('getConfigParam')->willReturnMap([['iDebug', $debug]]); + + /** @var d3DicHandler|MockObject $sut */ + $sut = $this->getMockBuilder(d3DicHandler::class) + ->onlyMethods(['d3GetConfig', 'd3GetCacheContainer', 'getContainerBuilder', 'isNotInTest', 'cacheFileExists']) + ->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); + + $this->assertSame( + $cachedContainer ? $cachedContainerMock : $containerBuilderMock, + $this->callMethod( + $sut, + 'buildContainer', + ['false'] + ) + ); + } + + /** + * @return Generator + */ + 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]; + } + + /** + * @test + * @return void + * @throws ReflectionException + * @covers \D3\DIContainerHandler\d3DicHandler::getContainerBuilder + */ + public function getContainerBuilderTest(): void + { + $sut = new d3DicHandler(); + + $this->assertInstanceOf( + ContainerBuilder::class, + $this->callMethod( + $sut, + 'getContainerBuilder' + ) + ); + } + + /**************/ + + + + /** + * Calls a private or protected object method. + * + * @param object $object + * @param string $methodName + * @param array $arguments + * + * @return mixed + * @throws ReflectionException + */ + public function callMethod($object, $methodName, array $arguments = []) + { + $class = new ReflectionClass($object); + $method = $class->getMethod($methodName); + $method->setAccessible(true); + return $method->invokeArgs($object, $arguments); + } + + /** + * Sets a private or protected property in defined class instance + * + * @param object $object + * @param string $valueName + * @param mixed $value + * @throws ReflectionException + */ + public function setValue($object, $valueName, $value) + { + $reflection = new ReflectionClass($object); + $property = $reflection->getProperty($valueName); + $property->setAccessible(true); + $property->setValue($object, $value); + } + + /** + * Sets a private or protected property in mocked class instance based on original class + * (required for e.g. final properties, which aren't contained in mock, but in original class) + * @param $mockedClassName * FQNS of original class + * @param $object * mock object + * @param $valueName * property name + * @param $value * new property value + * + * @throws ReflectionException + */ + public function setMockedClassValue($mockedClassName, $object, $valueName, $value) + { + $property = new \ReflectionProperty($mockedClassName, $valueName); + $property->setAccessible(true); + $property->setValue($object, $value); + } + + /** + * get a private or protected property from defined class instance + * + * @param object $object + * @param string $valueName + * @param mixed $value + * @return mixed + * @throws ReflectionException + */ + public function getValue($object, $valueName) + { + $reflection = new ReflectionClass($object); + $property = $reflection->getProperty($valueName); + $property->setAccessible(true); + return $property->getValue($object); + } + + /** + * get a private or protected property from mocked class instance based on original class + * (required for e.g. final properties, which aren't contained in mock, but in original class) + * @param object $object + * @param string $valueName + * @param mixed $value + * @return mixed + * @throws ReflectionException + */ + public function getMockedClassValue($mockedClassName, $object, $valueName) + { + $property = new \ReflectionProperty($mockedClassName, $valueName); + $property->setAccessible(true); + return $property->getValue($object); + } +} \ No newline at end of file diff --git a/tests/unit/d3DicUtilitiesTest.php b/tests/unit/d3DicUtilitiesTest.php new file mode 100644 index 0000000..368afed --- /dev/null +++ b/tests/unit/d3DicUtilitiesTest.php @@ -0,0 +1,194 @@ + + * @link https://www.oxidmodule.com + */ + +declare(strict_types=1); + +namespace D3\DIContainerHandler\tests; + +use D3\DIContainerHandler\d3DicHandler; +use D3\DIContainerHandler\d3DicUtilities; +use Generator; +use PHPUnit\Framework\TestCase; +use ReflectionClass; +use ReflectionException; + +class d3DicUtilitiesTest extends TestCase +{ + /** + * @test + * @param string $className + * @param string|null $additional + * @param $expected + * + * @return void + * @throws ReflectionException + * @covers \D3\DIContainerHandler\d3DicUtilities::getServiceId + * @dataProvider getServiceIdTestDataProvider + */ + public function getServiceIdTest(string $className, string $additional = null, $expected): void + { + $sut = oxNew(d3DicUtilities::class); + + $this->assertSame( + $expected, + $this->callMethod( + $sut, + 'getServiceId', + [$className, $additional] + ) + ); + } + + public function getServiceIdTestDataProvider(): Generator + { + yield 'NS only' => [d3DicHandler::class, null, 'd3\dicontainerhandler\d3dichandler']; + yield 'NS + additional' => [d3DicHandler::class, 'additional', 'additional.d3\dicontainerhandler\d3dichandler']; + } + + /** + * @test + * + * @param string $className + * @param string $argumentName + * @param $expected + * + * @return void + * @throws ReflectionException + * @covers \D3\DIContainerHandler\d3DicUtilities::getArgumentId + * @dataProvider getArgumentIdTestDataProvider + */ + public function getArgumentIdTest(string $className, string $argumentName, $expected): void + { + $sut = oxNew(d3DicUtilities::class); + + $this->assertSame( + $expected, + $this->callMethod( + $sut, + 'getArgumentId', + [ $className, $argumentName] + ) + ); + } + + public function getArgumentIdTestDataProvider(): Generator + { + yield 'default' => [d3DicHandler::class, 'argumentName', 'd3\dicontainerhandler\d3dichandler.args.argumentname']; + } + + /** + * @test + * @return void + * @throws ReflectionException + * @covers \D3\DIContainerHandler\d3DicUtilities::getVendorDir() + */ + public function getVendorDirTest(): void + { + $sut = oxNew(d3DicUtilities::class); + + $this->assertDirectoryExists( + $this->callMethod( + $sut, + 'getVendorDir' + ) + ); + } + + /**************/ + + + + /** + * Calls a private or protected object method. + * + * @param object $object + * @param string $methodName + * @param array $arguments + * + * @return mixed + * @throws ReflectionException + */ + public function callMethod($object, $methodName, array $arguments = []) + { + $class = new ReflectionClass($object); + $method = $class->getMethod($methodName); + $method->setAccessible(true); + return $method->invokeArgs($object, $arguments); + } + + /** + * Sets a private or protected property in defined class instance + * + * @param object $object + * @param string $valueName + * @param mixed $value + * @throws ReflectionException + */ + public function setValue($object, $valueName, $value) + { + $reflection = new ReflectionClass($object); + $property = $reflection->getProperty($valueName); + $property->setAccessible(true); + $property->setValue($object, $value); + } + + /** + * Sets a private or protected property in mocked class instance based on original class + * (required for e.g. final properties, which aren't contained in mock, but in original class) + * @param $mockedClassName * FQNS of original class + * @param $object * mock object + * @param $valueName * property name + * @param $value * new property value + * + * @throws ReflectionException + */ + public function setMockedClassValue($mockedClassName, $object, $valueName, $value) + { + $property = new \ReflectionProperty($mockedClassName, $valueName); + $property->setAccessible(true); + $property->setValue($object, $value); + } + + /** + * get a private or protected property from defined class instance + * + * @param object $object + * @param string $valueName + * @param mixed $value + * @return mixed + * @throws ReflectionException + */ + public function getValue($object, $valueName) + { + $reflection = new ReflectionClass($object); + $property = $reflection->getProperty($valueName); + $property->setAccessible(true); + return $property->getValue($object); + } + + /** + * get a private or protected property from mocked class instance based on original class + * (required for e.g. final properties, which aren't contained in mock, but in original class) + * @param object $object + * @param string $valueName + * @param mixed $value + * @return mixed + * @throws ReflectionException + */ + public function getMockedClassValue($mockedClassName, $object, $valueName) + { + $property = new \ReflectionProperty($mockedClassName, $valueName); + $property->setAccessible(true); + return $property->getValue($object); + } +} \ No newline at end of file diff --git a/tests/unit/definitionFileContainerTest.php b/tests/unit/definitionFileContainerTest.php new file mode 100644 index 0000000..d06224f --- /dev/null +++ b/tests/unit/definitionFileContainerTest.php @@ -0,0 +1,284 @@ + + * @link https://www.oxidmodule.com + */ + +declare(strict_types=1); + +namespace D3\DIContainerHandler\tests; + +use Assert\InvalidArgumentException; +use D3\DIContainerHandler\definitionFileContainer; +use Generator; +use PHPUnit\Framework\TestCase; +use ReflectionClass; +use ReflectionException; + +class definitionFileContainerTest extends TestCase +{ + /** + * @test + * + * @param $file + * @param $type + * @param $sumand + * @param bool $expectException + * + * @return void + * @throws ReflectionException + * @dataProvider addDefinitionsTestDataProvider + * @covers \D3\DIContainerHandler\definitionFileContainer::addDefinitions + */ + public function addDefinitionsTest($file, $type, $sumand, bool $expectException): void + { + $sut = oxNew(definitionFileContainer::class); + $sut->clear(); + + $currentCount = count($sut->getAll()); + + if ($expectException) { + $this->expectException(InvalidArgumentException::class); + } + + $this->callMethod( + $sut, + 'addDefinitions', + [$file, $type] + ); + + $this->assertCount( + $currentCount + $sumand, + $sut->getAll() + ); + } + + /** + * @return Generator + */ + public function addDefinitionsTestDataProvider(): Generator + { + yield 'invalid file' => ['foo.txt', definitionFileContainer::TYPE_YAML, 0, true]; + yield 'invalid type' => ['d3/modcfg/Config/services.yaml', 'txt', 0, true]; + yield 'ok' => ['d3/modcfg/Config/services.yaml', definitionFileContainer::TYPE_YAML, 1, false]; + } + + /** + * @test + * @return void + * @throws ReflectionException + * @covers \D3\DIContainerHandler\definitionFileContainer::addYamlDefinitions + */ + public function addYamlDefinitionsTest(): void + { + $sut = $this->getMockBuilder(definitionFileContainer::class) + ->onlyMethods(['addDefinitions']) + ->getMock(); + $sut->expects($this->once())->method('addDefinitions'); + + $this->callMethod( + $sut, + 'addYamlDefinitions', + ['d3/modcfg/Config/services.yaml'] + ); + } + + /** + * @test + * + * @param string $type + * @param bool $expectException + * + * @return void + * @throws ReflectionException + * @covers \D3\DIContainerHandler\definitionFileContainer::getDefinitions + * @dataProvider getDefinitionsTestDataProvider + */ + public function getDefinitionsTest(string $type, bool $expectException): void + { + $sut = oxNew(definitionFileContainer::class); + + if ($expectException) { + $this->expectException(InvalidArgumentException::class); + } + + $definitions = $this->callMethod( + $sut, + 'getDefinitions', + [$type] + ); + + $this->assertIsArray($definitions); + } + + /** + * @return Generator + */ + public function getDefinitionsTestDataProvider(): Generator + { + yield 'type ok' => [definitionFileContainer::TYPE_YAML, false]; + yield 'type not ok' => ['txt', true]; + } + + /** + * @test + * @return void + * @throws ReflectionException + * @covers \D3\DIContainerHandler\definitionFileContainer::getYamlDefinitions + */ + public function getYamlDefinitionsTest(): void + { + $sut = $this->getMockBuilder(definitionFileContainer::class) + ->onlyMethods(['getDefinitions']) + ->getMock(); + $sut->expects($this->once())->method('getDefinitions'); + + $this->callMethod( + $sut, + 'getYamlDefinitions' + ); + } + + /** + * @test + * @return void + * @throws ReflectionException + * @covers \D3\DIContainerHandler\definitionFileContainer::getAll + */ + public function getAllTest(): void + { + $fixture = ['foo']; + + $sut = oxNew(definitionFileContainer::class); + $this->setValue( + $sut, + 'definitionFiles', + $fixture + ); + + $this->assertSame( + $fixture, + $this->callMethod( + $sut, + 'getAll' + ) + ); + } + + /** + * @test + * @return void + * @throws ReflectionException + * @covers \D3\DIContainerHandler\definitionFileContainer::clear + */ + public function clearTest() + { + $sut = oxNew(definitionFileContainer::class); + $sut->addYamlDefinitions('d3/modcfg/Config/services.yaml'); + $sut->clear(); + + $this->assertCount( + 0, + $this->callMethod( + $sut, + 'getAll' + ) + ); + } + + + /**************/ + + + + /** + * Calls a private or protected object method. + * + * @param object $object + * @param string $methodName + * @param array $arguments + * + * @return mixed + * @throws ReflectionException + */ + public function callMethod($object, $methodName, array $arguments = []) + { + $class = new ReflectionClass($object); + $method = $class->getMethod($methodName); + $method->setAccessible(true); + return $method->invokeArgs($object, $arguments); + } + + /** + * Sets a private or protected property in defined class instance + * + * @param object $object + * @param string $valueName + * @param mixed $value + * @throws ReflectionException + */ + public function setValue($object, $valueName, $value) + { + $reflection = new ReflectionClass($object); + $property = $reflection->getProperty($valueName); + $property->setAccessible(true); + $property->setValue($object, $value); + } + + /** + * Sets a private or protected property in mocked class instance based on original class + * (required for e.g. final properties, which aren't contained in mock, but in original class) + * @param $mockedClassName * FQNS of original class + * @param $object * mock object + * @param $valueName * property name + * @param $value * new property value + * + * @throws ReflectionException + */ + public function setMockedClassValue($mockedClassName, $object, $valueName, $value) + { + $property = new \ReflectionProperty($mockedClassName, $valueName); + $property->setAccessible(true); + $property->setValue($object, $value); + } + + /** + * get a private or protected property from defined class instance + * + * @param object $object + * @param string $valueName + * @param mixed $value + * @return mixed + * @throws ReflectionException + */ + public function getValue($object, $valueName) + { + $reflection = new ReflectionClass($object); + $property = $reflection->getProperty($valueName); + $property->setAccessible(true); + return $property->getValue($object); + } + + /** + * get a private or protected property from mocked class instance based on original class + * (required for e.g. final properties, which aren't contained in mock, but in original class) + * @param object $object + * @param string $valueName + * @param mixed $value + * @return mixed + * @throws ReflectionException + */ + public function getMockedClassValue($mockedClassName, $object, $valueName) + { + $property = new \ReflectionProperty($mockedClassName, $valueName); + $property->setAccessible(true); + return $property->getValue($object); + } +} \ No newline at end of file