Skip to content

Commit 14383a5

Browse files
committed
Add ability to set default value for any functions
1 parent 2435a87 commit 14383a5

File tree

8 files changed

+2079
-2286
lines changed

8 files changed

+2079
-2286
lines changed

composer.lock

Lines changed: 1881 additions & 2247 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Mocker.php

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<?php
2+
23
declare(strict_types=1);
34

45
namespace Xepozz\InternalMocker;
@@ -7,21 +8,23 @@
78

89
final class Mocker
910
{
10-
private string $path;
11-
12-
public function __construct(string $path = __DIR__ . '/../data/mocks.php')
11+
public function __construct(private string $path = __DIR__ . '/../data/mocks.php')
1312
{
14-
$this->path = $path;
1513
}
1614

1715
public function load(array $mocks): void
1816
{
1917
$data = "<?php\n\n";
2018
$data .= $this->generate($mocks);
19+
$configPath = $this->getConfigPath();
20+
$directoryPath = dirname($configPath);
2121

22-
file_put_contents($this->getConfigPath(), $data);
22+
if (!is_dir($directoryPath)) {
23+
mkdir($directoryPath, 0775, true);
24+
}
25+
file_put_contents($configPath, $data);
2326

24-
require $this->getConfigPath();
27+
require $configPath;
2528
}
2629

2730
public function generate(array $mocks): string
@@ -36,15 +39,16 @@ public function generate(array $mocks): string
3639
}
3740
$argumentsString = VarDumper::create($imock['arguments'])->export(false);
3841
$resultString = VarDumper::create($imock['result'])->export(false);
42+
$defaultString = $imock['default'] ? 'true' : 'false';
3943
$mockerConfig[] = <<<PHP
4044
MockerState::addCondition(
4145
"$namespace",
4246
"$functionName",
43-
{$argumentsString},
44-
{$resultString}
47+
$argumentsString,
48+
$resultString,
49+
$defaultString,
4550
);
4651
PHP;
47-
4852
}
4953
}
5054
}
@@ -77,22 +81,23 @@ private function normalizeMocks(array $mocks): array
7781
'result' => $mock['result'] ?? null,
7882
'arguments' => $mock['arguments'] ?? [],
7983
'skip' => !array_key_exists('result', $mock),
84+
'default' => $mock['default'] ?? false,
8085
];
8186
}
8287
return $result;
8388
}
8489

85-
private function generateFunction(mixed $grouppedMocks): string
90+
private function generateFunction(mixed $groupedMocks): string
8691
{
8792
$innerOutputs = [];
88-
foreach ($grouppedMocks as $functionName => $_) {
93+
foreach ($groupedMocks as $functionName => $_) {
8994
$string = <<<PHP
90-
function {$functionName}(...\$arguments)
95+
function $functionName(...\$arguments)
9196
{
9297
if (MockerState::checkCondition(__NAMESPACE__, "$functionName", \$arguments)) {
9398
return MockerState::getResult(__NAMESPACE__, "$functionName", \$arguments);
9499
}
95-
return \\{$functionName}(...\$arguments);
100+
return MockerState::getDefaultResult(__NAMESPACE__, "$functionName", fn() => \\$functionName(...\$arguments));
96101
}
97102
PHP;
98103
$innerOutputs[] = $string;

src/MockerState.php

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<?php
2+
23
declare(strict_types=1);
34

45
namespace Xepozz\InternalMocker;
@@ -7,9 +8,20 @@ final class MockerState
78
{
89
private static array $savedState = [];
910
private static array $state = [];
11+
private static array $defaults = [];
12+
13+
public static function addCondition(
14+
string $namespace,
15+
string $functionName,
16+
array $arguments,
17+
mixed $result,
18+
bool $default = false
19+
): void {
20+
if ($default) {
21+
self::$defaults[$namespace][$functionName] = $result;
22+
return;
23+
}
1024

11-
public static function addCondition(string $namespace, string $functionName, array $arguments, $result)
12-
{
1325
if (self::checkCondition($namespace, $functionName, $arguments)) {
1426
self::replaceResult($namespace, $functionName, $arguments, $result);
1527
return;
@@ -23,25 +35,33 @@ public static function addCondition(string $namespace, string $functionName, arr
2335
];
2436
}
2537

26-
public static function checkCondition(string $namespace, string $functionName, array $expectedArguments): bool
27-
{
38+
public static function checkCondition(
39+
string $namespace,
40+
string $functionName,
41+
array $expectedArguments,
42+
): bool {
2843
$mocks = self::$state[$namespace][$functionName] ?? [];
2944

3045
foreach ($mocks as $mock) {
31-
if (self::compareArguments($mock['arguments'], $expectedArguments)) {
46+
if (self::compareArguments($mock, $expectedArguments)) {
3247
return true;
3348
}
3449
}
3550
return false;
3651
}
3752

38-
private static function compareArguments($arguments, array $expectedArguments): bool
53+
private static function compareArguments(array $arguments, array $expectedArguments): bool
3954
{
40-
return $arguments === $expectedArguments || array_values($arguments) === $expectedArguments;
55+
return $arguments['arguments'] === $expectedArguments
56+
|| array_values($arguments['arguments']) === $expectedArguments;
4157
}
4258

43-
private static function replaceResult(string $namespace, string $functionName, array $arguments, $result): void
44-
{
59+
private static function replaceResult(
60+
string $namespace,
61+
string $functionName,
62+
array $arguments,
63+
mixed $result,
64+
): void {
4565
$mocks = &self::$state[$namespace][$functionName];
4666

4767
foreach ($mocks as &$mock) {
@@ -51,24 +71,39 @@ private static function replaceResult(string $namespace, string $functionName, a
5171
}
5272
}
5373

54-
public static function getResult(string $namespace, string $functionName, array $expectedArguments)
55-
{
74+
public static function getResult(
75+
string $namespace,
76+
string $functionName,
77+
array $expectedArguments,
78+
): mixed {
5679
$mocks = self::$state[$namespace][$functionName] ?? [];
5780

5881
foreach ($mocks as $mock) {
59-
if (self::compareArguments($mock['arguments'], $expectedArguments)) {
82+
if (self::compareArguments($mock, $expectedArguments)) {
6083
return $mock['result'];
6184
}
6285
}
6386
return false;
6487
}
6588

66-
public static function saveState()
89+
public static function getDefaultResult(
90+
string $namespace,
91+
string $functionName,
92+
callable $fallback,
93+
): mixed {
94+
if (isset(self::$defaults[$namespace][$functionName])) {
95+
return self::$defaults[$namespace][$functionName];
96+
}
97+
98+
return $fallback();
99+
}
100+
101+
public static function saveState(): void
67102
{
68103
self::$savedState = self::$state;
69104
}
70105

71-
public static function resetState()
106+
public static function resetState(): void
72107
{
73108
self::$state = self::$savedState;
74109
}

src/Stub.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Xepozz\InternalMocker;
6+
7+
use RuntimeException;
8+
9+
class Stub
10+
{
11+
public function __construct()
12+
{
13+
if (!function_exists('function_exists')) {
14+
throw new RuntimeException('The function `function_exists` is not registered.');
15+
}
16+
}
17+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Xepozz\InternalMocker\Tests\Integration;
6+
7+
use PHPUnit\Framework\TestCase;
8+
use RuntimeException;
9+
use Xepozz\InternalMocker\MockerState;
10+
use Xepozz\InternalMocker\Stub;
11+
12+
class FunctionExistsTest extends TestCase
13+
{
14+
public function testSuccess()
15+
{
16+
MockerState::addCondition(
17+
'Xepozz\\InternalMocker',
18+
'function_exists',
19+
['function_exists'],
20+
false
21+
);
22+
23+
$this->expectException(RuntimeException::class);
24+
new Stub();
25+
}
26+
27+
public function testFail()
28+
{
29+
MockerState::addCondition(
30+
'Xepozz\\InternalMocker',
31+
'function_exists',
32+
['function_exists'],
33+
true
34+
);
35+
36+
new Stub();
37+
$this->assertTrue(true);
38+
}
39+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Xepozz\InternalMocker\Tests\Integration;
6+
7+
use PHPUnit\Framework\TestCase;
8+
use Xepozz\InternalMocker\MockerState;
9+
10+
class IgnoreArgumentsTest extends TestCase
11+
{
12+
/**
13+
* @dataProvider dataProvider
14+
*/
15+
public function testSuccessByCase(string $class): void
16+
{
17+
MockerState::addCondition(
18+
__NAMESPACE__,
19+
'class_exists',
20+
[],
21+
true,
22+
);
23+
24+
$this->assertTrue(class_exists($class));
25+
}
26+
27+
/**
28+
* @dataProvider dataProvider
29+
*/
30+
public function testSuccessByDefault(string $class): void
31+
{
32+
MockerState::addCondition(
33+
__NAMESPACE__,
34+
'class_exists',
35+
[],
36+
true,
37+
true
38+
);
39+
40+
$this->assertTrue(class_exists($class));
41+
}
42+
43+
public function dataProvider(): array
44+
{
45+
return [
46+
['A'],
47+
['B'],
48+
['[{}]'],
49+
];
50+
}
51+
}

tests/Listener.php

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,29 +13,39 @@ final class Listener implements BeforeFirstTestHook, BeforeTestHook
1313
public function executeBeforeFirstTest(): void
1414
{
1515
$mocks = [
16+
[
17+
'namespace' => 'Xepozz\\InternalMocker',
18+
'name' => 'function_exists',
19+
],
1620
[
1721
'namespace' => 'Xepozz\InternalMocker\Tests\Integration',
22+
'name' => 'class_exists',
23+
'default' => true,
24+
'result' => true,
25+
],
26+
[
27+
'namespace' => 'Xepozz\\InternalMocker\\Tests\\Integration',
1828
'name' => 'time',
19-
'result' => 555,
2029
'arguments' => [],
30+
'result' => 555,
2131
],
2232
[
23-
'namespace' => 'Xepozz\InternalMocker\Tests\Integration',
33+
'namespace' => 'Xepozz\\InternalMocker\\Tests\\Integration',
2434
'name' => 'str_contains',
25-
'result' => false,
2635
'arguments' => [
2736
'haystack' => 'string',
2837
'needle' => 'str',
2938
],
39+
'result' => false,
3040
],
3141
[
32-
'namespace' => 'Xepozz\InternalMocker\Tests\Integration',
42+
'namespace' => 'Xepozz\\InternalMocker\\Tests\\Integration',
3343
'name' => 'str_contains',
34-
'result' => false,
3544
'arguments' => [
3645
'haystack' => 'string2',
3746
'needle' => 'str',
3847
],
48+
'result' => false,
3949
],
4050
[
4151
'namespace' => 'ASD',

0 commit comments

Comments
 (0)