Skip to content

Instantly share code, notes, and snippets.

@dasbairagya
Last active March 5, 2023 12:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dasbairagya/a654eb9d5fa84e15d81d3648518567b6 to your computer and use it in GitHub Desktop.
Save dasbairagya/a654eb9d5fa84e15d81d3648518567b6 to your computer and use it in GitHub Desktop.
How to mock a final class and private method
<?php
namespace UnitTest\App;
final class FinalClass
{
public function __construct()
{
}
/**
* int $number
*
* @retun int
*/
private function IamPrivate(int $number): int
{
return ($number!=2) ? $number : 0;
}
/**
* int $number
*
* @retun int
*/
public function getNumber($num): int
{
return $num;
}
}
?>
//----------------------------------------------------------------------------------
<?php
use UnitTest\App\FinalClass;
use PHPUnit\Framework\TestCase;
use DG\BypassFinals;
final class FinalClassTest extends TestCase
{
protected $finalClass;
private $mock;
private $reflector;
protected function setUp(): void
{
BypassFinals::enable(); //only required for mocking but not required in reflection
$this->finalClass = new FinalClass();
}
/**
* How to mock a final class
*
* @test
* @return void
*/
public function getNumber(): void
{
$this->mock = $this->createMock(FinalClass::class);
$this->mock->method('getNumber')
->with(3)
->willReturn(3);
$result = $this->mock->getNumber(3);
$this->assertEquals(3, $result);
}
/**
* How to access the private method using reflection class
*
* @test
* @return void
*/
public function IamPrivate(): void
{
$number = 2;
$method = $this->getPrivateMethod( FinalClass::class, 'IamPrivate' );;
$result = $method->invokeArgs( $this->finalClass, array( $number ) );
$this->assertEquals( 0, $result );
}
/**
* getPrivateMethod
*
* @author Gopal Dasbairagya <gopal.dasbairagya@tcs.com>
* @param string $className
* @param string $methodName
* @return ReflectionMethod
*/
public function getPrivateMethod( $className, $methodName ) {
$reflector = new ReflectionClass( $className );
$method = $reflector->getMethod( $methodName );
$method->setAccessible( true );
return $method;
}
}
?>
@dasbairagya
Copy link
Author

You need to run composer require dg/bypass-finals --dev if you want to only mock a final class. For reflection it is not required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment