From dd0a0213238b27280aac39e263cd1be3b4fdb4f0 Mon Sep 17 00:00:00 2001 From: mbrostami Date: Tue, 15 Oct 2019 00:05:08 +0200 Subject: [PATCH 1/3] unit test to reproduce single method except issue --- tests/_files/ClassWithSinglePublicMethod.php | 20 +++++++++++++++++++ .../Framework/MockObject/MockBuilderTest.php | 9 +++++++++ 2 files changed, 29 insertions(+) create mode 100644 tests/_files/ClassWithSinglePublicMethod.php diff --git a/tests/_files/ClassWithSinglePublicMethod.php b/tests/_files/ClassWithSinglePublicMethod.php new file mode 100644 index 00000000000..0b4aabc73aa --- /dev/null +++ b/tests/_files/ClassWithSinglePublicMethod.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * A class with only one public method + */ +class ClassWithSinglePublicMethod +{ + public function falseReturn() + { + return false; + } +} diff --git a/tests/unit/Framework/MockObject/MockBuilderTest.php b/tests/unit/Framework/MockObject/MockBuilderTest.php index 5d9e3c9fa63..707627eaaf9 100644 --- a/tests/unit/Framework/MockObject/MockBuilderTest.php +++ b/tests/unit/Framework/MockObject/MockBuilderTest.php @@ -126,4 +126,13 @@ public function testProvidesAFluentInterface(): void $this->assertInstanceOf(MockBuilder::class, $spec); } + + public function testExceptMethodFromClassWithSinglePublicMethod(): void + { + $spec = $this->getMockBuilder(ClassWithSinglePublicMethod::class) + ->setMethodsExcept(['falseReturn']) + ->getMock(); + + $this->assertFalse($spec->falseReturn()); + } } From 9d7b21ad0081f91fd07059bbf7af46389583de13 Mon Sep 17 00:00:00 2001 From: Mohamed Rostrami Date: Tue, 15 Oct 2019 17:08:52 +0200 Subject: [PATCH 2/3] pass excepted methods to generator --- src/Framework/MockObject/Generator.php | 55 ++++++++++++++++-------- src/Framework/MockObject/MockBuilder.php | 9 ++-- src/Framework/TestCase.php | 7 ++- 3 files changed, 48 insertions(+), 23 deletions(-) diff --git a/src/Framework/MockObject/Generator.php b/src/Framework/MockObject/Generator.php index c7300f761b1..8c8164c31df 100644 --- a/src/Framework/MockObject/Generator.php +++ b/src/Framework/MockObject/Generator.php @@ -66,15 +66,12 @@ class Generator * @param object $proxyTarget * @param bool $allowMockingUnknownTypes * @param bool $returnValueGeneration - * - * @throws Exception - * @throws RuntimeException - * @throws \PHPUnit\Framework\Exception - * @throws \ReflectionException + * @param array $methodsExcepted * * @return MockObject + * @throws \ReflectionException */ - public function getMock($type, $methods = [], array $arguments = [], $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $cloneArguments = true, $callOriginalMethods = false, $proxyTarget = null, $allowMockingUnknownTypes = true, $returnValueGeneration = true) + public function getMock($type, $methods = [], array $arguments = [], $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $cloneArguments = true, $callOriginalMethods = false, $proxyTarget = null, $allowMockingUnknownTypes = true, $returnValueGeneration = true, array $methodsExcepted = []) { if (!\is_array($type) && !\is_string($type)) { throw InvalidArgumentHelper::factory(1, 'array or string'); @@ -185,7 +182,8 @@ function ($type) { $callOriginalClone, $callAutoload, $cloneArguments, - $callOriginalMethods + $callOriginalMethods, + $methodsExcepted ); return $this->getObject( @@ -207,12 +205,14 @@ function ($type) { * the last parameter * * @param string $originalClassName + * @param array $arguments * @param string $mockClassName * @param bool $callOriginalConstructor * @param bool $callOriginalClone * @param bool $callAutoload * @param array $mockedMethods * @param bool $cloneArguments + * @param array $methodsExcept * * @throws \ReflectionException * @throws RuntimeException @@ -220,7 +220,7 @@ function ($type) { * * @return MockObject */ - public function getMockForAbstractClass($originalClassName, array $arguments = [], $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $mockedMethods = [], $cloneArguments = true) + public function getMockForAbstractClass($originalClassName, array $arguments = [], $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $mockedMethods = [], $cloneArguments = true, array $methodsExcept = []) { if (!\is_string($originalClassName)) { throw InvalidArgumentHelper::factory(1, 'string'); @@ -253,7 +253,12 @@ public function getMockForAbstractClass($originalClassName, array $arguments = [ $callOriginalConstructor, $callOriginalClone, $callAutoload, - $cloneArguments + $cloneArguments, + false, + null, + true, + true, + $methodsExcept ); } @@ -268,12 +273,14 @@ public function getMockForAbstractClass($originalClassName, array $arguments = [ * `$mockedMethods` parameter. * * @param string $traitName + * @param array $arguments * @param string $mockClassName * @param bool $callOriginalConstructor * @param bool $callOriginalClone * @param bool $callAutoload * @param array $mockedMethods * @param bool $cloneArguments + * @param array $methodsExcept * * @throws \ReflectionException * @throws RuntimeException @@ -281,7 +288,7 @@ public function getMockForAbstractClass($originalClassName, array $arguments = [ * * @return MockObject */ - public function getMockForTrait($traitName, array $arguments = [], $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $mockedMethods = [], $cloneArguments = true) + public function getMockForTrait($traitName, array $arguments = [], $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $mockedMethods = [], $cloneArguments = true, array $methodsExcept = []) { if (!\is_string($traitName)) { throw InvalidArgumentHelper::factory(1, 'string'); @@ -321,7 +328,7 @@ public function getMockForTrait($traitName, array $arguments = [], $mockClassNam $className['className'] ); - return $this->getMockForAbstractClass($className['className'], $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $mockedMethods, $cloneArguments); + return $this->getMockForAbstractClass($className['className'], $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload, $mockedMethods, $cloneArguments, $methodsExcept); } /** @@ -392,13 +399,14 @@ public function getObjectForTrait($traitName, array $arguments = [], $traitClass * @param bool $callAutoload * @param bool $cloneArguments * @param bool $callOriginalMethods + * @param array $methodsExcepted * * @throws \ReflectionException * @throws \PHPUnit\Framework\MockObject\RuntimeException * * @return array */ - public function generate($type, array $methods = null, $mockClassName = '', $callOriginalClone = true, $callAutoload = true, $cloneArguments = true, $callOriginalMethods = false) + public function generate($type, array $methods = null, $mockClassName = '', $callOriginalClone = true, $callAutoload = true, $cloneArguments = true, $callOriginalMethods = false, array $methodsExcepted = []) { if (\is_array($type)) { \sort($type); @@ -412,12 +420,14 @@ public function generate($type, array $methods = null, $mockClassName = '', $cal $callOriginalClone, $callAutoload, $cloneArguments, - $callOriginalMethods + $callOriginalMethods, + $methodsExcepted ); } $key = \md5( \is_array($type) ? \implode('_', $type) : $type . \serialize($methods) . + \serialize($methodsExcepted) . \serialize($callOriginalClone) . \serialize($cloneArguments) . \serialize($callOriginalMethods) @@ -431,7 +441,8 @@ public function generate($type, array $methods = null, $mockClassName = '', $cal $callOriginalClone, $callAutoload, $cloneArguments, - $callOriginalMethods + $callOriginalMethods, + $methodsExcepted ); } @@ -544,16 +555,23 @@ public function getClassMethods($className): array } /** - * @throws \ReflectionException + * @param string $className + * @param bool $callOriginalMethods + * @param bool $cloneArguments + * @param array $methodsExcepted * * @return MockMethod[] + * @throws \ReflectionException */ - public function mockClassMethods(string $className, bool $callOriginalMethods, bool $cloneArguments): array + public function mockClassMethods(string $className, bool $callOriginalMethods, bool $cloneArguments, array $methodsExcepted = []): array { $class = new ReflectionClass($className); $methods = []; foreach ($class->getMethods() as $method) { + if ($methodsExcepted !== [] && in_array($method->getName(), $methodsExcepted)) { + continue; + } if (($method->isPublic() || $method->isAbstract()) && $this->canMockMethod($method)) { $methods[] = MockMethod::fromReflection($method, $callOriginalMethods, $cloneArguments); } @@ -655,6 +673,7 @@ private function evalClass($code, $className): void * @param bool $callAutoload * @param bool $cloneArguments * @param bool $callOriginalMethods + * @param array $methodsExcepted * * @throws \InvalidArgumentException * @throws \ReflectionException @@ -662,7 +681,7 @@ private function evalClass($code, $className): void * * @return array */ - private function generateMock($type, $explicitMethods, $mockClassName, $callOriginalClone, $callAutoload, $cloneArguments, $callOriginalMethods) + private function generateMock($type, $explicitMethods, $mockClassName, $callOriginalClone, $callAutoload, $cloneArguments, $callOriginalMethods, $methodsExcepted) { $classTemplate = $this->getTemplate('mocked_class.tpl'); @@ -830,7 +849,7 @@ private function generateMock($type, $explicitMethods, $mockClassName, $callOrig if ($explicitMethods === [] && ($isClass || $isInterface)) { $mockMethods->addMethods( - ...$this->mockClassMethods($mockClassName['fullClassName'], $callOriginalMethods, $cloneArguments) + ...$this->mockClassMethods($mockClassName['fullClassName'], $callOriginalMethods, $cloneArguments, $methodsExcepted) ); } diff --git a/src/Framework/MockObject/MockBuilder.php b/src/Framework/MockObject/MockBuilder.php index 3199afd6db4..8f060b7d1dd 100644 --- a/src/Framework/MockObject/MockBuilder.php +++ b/src/Framework/MockObject/MockBuilder.php @@ -120,7 +120,8 @@ public function getMock() $this->callOriginalMethods, $this->proxyTarget, $this->allowMockingUnknownTypes, - $this->returnValueGeneration + $this->returnValueGeneration, + $this->methodsExcept ); $this->testCase->registerMockObject($object); @@ -143,7 +144,8 @@ public function getMockForAbstractClass() $this->originalClone, $this->autoload, $this->methods, - $this->cloneArguments + $this->cloneArguments, + $this->methodsExcept ); $this->testCase->registerMockObject($object); @@ -166,7 +168,8 @@ public function getMockForTrait() $this->originalClone, $this->autoload, $this->methods, - $this->cloneArguments + $this->cloneArguments, + $this->methodsExcept ); $this->testCase->registerMockObject($object); diff --git a/src/Framework/TestCase.php b/src/Framework/TestCase.php index 82f702001a4..2345dd35d31 100644 --- a/src/Framework/TestCase.php +++ b/src/Framework/TestCase.php @@ -1487,18 +1487,20 @@ protected function getMockFromWsdl($wsdlFile, $originalClassName = '', $mockClas * `$mockedMethods` parameter. * * @param string $traitName + * @param array $arguments * @param string $mockClassName * @param bool $callOriginalConstructor * @param bool $callOriginalClone * @param bool $callAutoload * @param array $mockedMethods * @param bool $cloneArguments + * @param array $methodsExcept * * @throws Exception * @throws ReflectionException * @throws \InvalidArgumentException */ - protected function getMockForTrait($traitName, array $arguments = [], $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $mockedMethods = [], $cloneArguments = false): MockObject + protected function getMockForTrait($traitName, array $arguments = [], $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $mockedMethods = [], $cloneArguments = false, array $methodsExcept = []): MockObject { $mockObject = $this->getMockObjectGenerator()->getMockForTrait( $traitName, @@ -1508,7 +1510,8 @@ protected function getMockForTrait($traitName, array $arguments = [], $mockClass $callOriginalClone, $callAutoload, $mockedMethods, - $cloneArguments + $cloneArguments, + $methodsExcept ); $this->registerMockObject($mockObject); From a44b624a28533389cd61ebba076f2d0239f8a5b1 Mon Sep 17 00:00:00 2001 From: mbrostami Date: Tue, 15 Oct 2019 17:19:59 +0200 Subject: [PATCH 3/3] fix cs-fixer suggestions --- src/Framework/MockObject/Generator.php | 18 +++++------------- src/Framework/TestCase.php | 2 -- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/src/Framework/MockObject/Generator.php b/src/Framework/MockObject/Generator.php index 8c8164c31df..6285241764a 100644 --- a/src/Framework/MockObject/Generator.php +++ b/src/Framework/MockObject/Generator.php @@ -66,10 +66,10 @@ class Generator * @param object $proxyTarget * @param bool $allowMockingUnknownTypes * @param bool $returnValueGeneration - * @param array $methodsExcepted * - * @return MockObject * @throws \ReflectionException + * + * @return MockObject */ public function getMock($type, $methods = [], array $arguments = [], $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $cloneArguments = true, $callOriginalMethods = false, $proxyTarget = null, $allowMockingUnknownTypes = true, $returnValueGeneration = true, array $methodsExcepted = []) { @@ -205,14 +205,12 @@ function ($type) { * the last parameter * * @param string $originalClassName - * @param array $arguments * @param string $mockClassName * @param bool $callOriginalConstructor * @param bool $callOriginalClone * @param bool $callAutoload * @param array $mockedMethods * @param bool $cloneArguments - * @param array $methodsExcept * * @throws \ReflectionException * @throws RuntimeException @@ -273,14 +271,12 @@ public function getMockForAbstractClass($originalClassName, array $arguments = [ * `$mockedMethods` parameter. * * @param string $traitName - * @param array $arguments * @param string $mockClassName * @param bool $callOriginalConstructor * @param bool $callOriginalClone * @param bool $callAutoload * @param array $mockedMethods * @param bool $cloneArguments - * @param array $methodsExcept * * @throws \ReflectionException * @throws RuntimeException @@ -399,7 +395,6 @@ public function getObjectForTrait($traitName, array $arguments = [], $traitClass * @param bool $callAutoload * @param bool $cloneArguments * @param bool $callOriginalMethods - * @param array $methodsExcepted * * @throws \ReflectionException * @throws \PHPUnit\Framework\MockObject\RuntimeException @@ -555,13 +550,9 @@ public function getClassMethods($className): array } /** - * @param string $className - * @param bool $callOriginalMethods - * @param bool $cloneArguments - * @param array $methodsExcepted + * @throws \ReflectionException * * @return MockMethod[] - * @throws \ReflectionException */ public function mockClassMethods(string $className, bool $callOriginalMethods, bool $cloneArguments, array $methodsExcepted = []): array { @@ -569,9 +560,10 @@ public function mockClassMethods(string $className, bool $callOriginalMethods, b $methods = []; foreach ($class->getMethods() as $method) { - if ($methodsExcepted !== [] && in_array($method->getName(), $methodsExcepted)) { + if ($methodsExcepted !== [] && \in_array($method->getName(), $methodsExcepted)) { continue; } + if (($method->isPublic() || $method->isAbstract()) && $this->canMockMethod($method)) { $methods[] = MockMethod::fromReflection($method, $callOriginalMethods, $cloneArguments); } diff --git a/src/Framework/TestCase.php b/src/Framework/TestCase.php index 2345dd35d31..ebe5d5eaed5 100644 --- a/src/Framework/TestCase.php +++ b/src/Framework/TestCase.php @@ -1487,14 +1487,12 @@ protected function getMockFromWsdl($wsdlFile, $originalClassName = '', $mockClas * `$mockedMethods` parameter. * * @param string $traitName - * @param array $arguments * @param string $mockClassName * @param bool $callOriginalConstructor * @param bool $callOriginalClone * @param bool $callAutoload * @param array $mockedMethods * @param bool $cloneArguments - * @param array $methodsExcept * * @throws Exception * @throws ReflectionException