-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(functions): add support for mocking function
- Loading branch information
Showing
17 changed files
with
467 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
/vendor/ | ||
/composer.lock | ||
/test/report-junit.xml | ||
/test/phpunit.cache.xml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:noNamespaceSchemaLocation="./vendor/squizlabs/php_codesniffer/phpcs.xsd"> | ||
|
||
<!-- General options --> | ||
<!-- see https://github.com/squizlabs/PHP_CodeSniffer/wiki/Usage --> | ||
<arg name="basepath" value="."/> | ||
<arg name="extensions" value="php"/> | ||
<arg name="report" value="full"/> | ||
<arg name="ignore" value="vendor"/> | ||
<arg value="psv"/> | ||
<config name="ignore_warnings_on_exit" value="1"/> | ||
|
||
<!-- Target --> | ||
<file>./src</file> | ||
<file>./test</file> | ||
|
||
<!-- Rules section --> | ||
<rule ref="PSR12"> | ||
</rule> | ||
</ruleset> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
parameters: | ||
level: max | ||
paths: | ||
- ./src | ||
- ./test | ||
bootstrapFiles: | ||
- ./test/phpstan/runkit7.stub.php |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace QratorLabs\Smocky\Functions; | ||
|
||
use QratorLabs\Smocky\MockedEntity; | ||
|
||
abstract class BaseFunction extends MockedEntity | ||
{ | ||
|
||
/** | ||
* @var ?string | ||
*/ | ||
protected $namespace = null; | ||
|
||
/** @var string */ | ||
protected $function; | ||
|
||
/** @var string */ | ||
protected $stashedName; | ||
|
||
/** | ||
* BaseFunction constructor. | ||
* | ||
* @param string $function | ||
*/ | ||
abstract public function __construct(string $function); | ||
|
||
public function getShortName(): string | ||
{ | ||
return $this->function; | ||
} | ||
|
||
public function getFullName(): string | ||
{ | ||
return $this->namespace === null ? $this->function : ($this->namespace . '\\' . $this->function); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace QratorLabs\Smocky\Functions; | ||
|
||
use Closure; | ||
use ReflectionException; | ||
|
||
use function runkit7_function_add; | ||
use function runkit7_function_remove; | ||
use function runkit7_function_rename; | ||
|
||
class MockedFunction extends UndefinedFunction | ||
{ | ||
|
||
/** @var Closure */ | ||
protected $closure; | ||
|
||
/** | ||
* @param string $function | ||
* @param Closure|null $closure | ||
* | ||
* @throws ReflectionException | ||
*/ | ||
public function __construct(string $function, Closure $closure = null) | ||
{ | ||
$this->closure = | ||
$closure ?? | ||
static function (): void { | ||
}; | ||
|
||
parent::__construct($function); | ||
$closure = $this->closure; | ||
$tmpName = $this->getStashedName($this->function); | ||
runkit7_function_add( | ||
$tmpName, | ||
/** | ||
* @param array<mixed> $args | ||
* | ||
* @return mixed | ||
*/ | ||
static function (...$args) use ($closure) { | ||
return $closure(...$args); | ||
} | ||
); | ||
runkit7_function_rename($tmpName, $this->getFullName()); | ||
} | ||
|
||
public function __destruct() | ||
{ | ||
if (isset($this->stashedName)) { | ||
runkit7_function_remove($this->getFullName()); | ||
parent::__destruct(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace QratorLabs\Smocky\Functions; | ||
|
||
use ReflectionException; | ||
use ReflectionFunction; | ||
|
||
use function runkit7_function_rename; | ||
|
||
class UndefinedFunction extends BaseFunction | ||
{ | ||
|
||
/** | ||
* @param string $function | ||
* | ||
* @throws ReflectionException | ||
*/ | ||
public function __construct(string $function) | ||
{ | ||
try { | ||
$reflection = new ReflectionFunction($function); | ||
} catch (ReflectionException $exception) { | ||
throw new ReflectionException( | ||
'Failed to create reflection: ' . $exception->getMessage(), | ||
$exception->getCode(), | ||
$exception | ||
); | ||
} | ||
|
||
$this->namespace = $reflection->inNamespace() ? $reflection->getNamespaceName() : null; | ||
$this->function = $reflection->getShortName(); | ||
|
||
$this->stashedName = $this->getStashedName($this->function); | ||
runkit7_function_rename($this->getFullName(), $this->stashedName); | ||
} | ||
|
||
public function __destruct() | ||
{ | ||
if (isset($this->stashedName)) { | ||
runkit7_function_rename($this->stashedName, $this->getFullName()); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace QratorLabs\Smocky\Phpunit; | ||
|
||
use PHPUnit\Framework\MockObject\Builder\InvocationMocker; | ||
use PHPUnit\Framework\MockObject\Rule\InvocationOrder; | ||
use PHPUnit\Framework\TestCase; | ||
use QratorLabs\Smocky\EmptyClass; | ||
use QratorLabs\Smocky\Functions\MockedFunction as GenericMockedFunction; | ||
use ReflectionException; | ||
|
||
class MockedFunction | ||
{ | ||
/** @var GenericMockedFunction */ | ||
private $mockedFunction; | ||
|
||
/** @var InvocationMocker */ | ||
private $invocationMocker; | ||
|
||
/** | ||
* MockedMethod constructor. | ||
* | ||
* @param TestCase $testCase | ||
* @param string $function | ||
* @param InvocationOrder|null $invocationRule | ||
* | ||
* @throws ReflectionException | ||
* | ||
* @noinspection UnusedConstructorDependenciesInspection | ||
*/ | ||
public function __construct( | ||
TestCase $testCase, | ||
string $function, | ||
InvocationOrder $invocationRule = null | ||
) { | ||
$mockObject = null; | ||
$method = null; | ||
|
||
$this->mockedFunction = new GenericMockedFunction( | ||
$function, | ||
/** | ||
* @param array<mixed> $args | ||
* | ||
* @return mixed | ||
*/ | ||
static function (...$args) use (&$mockObject, &$method) { | ||
return $mockObject->{$method}(...$args); | ||
} | ||
); | ||
|
||
$method = $this->mockedFunction->getShortName(); | ||
$mockObject = $testCase->getMockBuilder(EmptyClass::class) | ||
->disableOriginalConstructor() | ||
->disableOriginalClone() | ||
->disableArgumentCloning() | ||
->disallowMockingUnknownTypes() | ||
->addMethods([$method]) | ||
->getMock(); | ||
|
||
if ($invocationRule === null) { | ||
$this->invocationMocker = $mockObject->method($method); | ||
} else { | ||
$this->invocationMocker = $mockObject->expects($invocationRule)->method($method); | ||
} | ||
} | ||
|
||
public function getMocker(): InvocationMocker | ||
{ | ||
return $this->invocationMocker; | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.