Skip to content

Commit e309ba9

Browse files
committed
Initial commit
1 parent 6ea20dc commit e309ba9

File tree

5 files changed

+216
-1
lines changed

5 files changed

+216
-1
lines changed

.gitattributes

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.gitattributes export-ignore
2+
.gitignore export-ignore
3+
docs export-ignore
4+
tests export-ignore

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
vendor
2+
composer.lock

README.md

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,46 @@
11
# DependencyMocker
2-
Loads dependencies to mocked class in Nette Framework environment.
2+
Loads dependencies to mocked classes by Mockery for Nette Framework.
3+
4+
## Usage
5+
6+
### Set up
7+
8+
Banned Classes
9+
10+
Data entities, classes with different implementations of mockery magic (e.g. `__getStatic()`) etc.
11+
12+
```
13+
Spamer\DependencyMocker\Mocker::setBannedClasses([
14+
App\Entity\BaseEntity::class,
15+
App\GetStatic::class,
16+
]);
17+
```
18+
19+
### Mock Class
20+
```
21+
$basePresenter = Spamer\DependencyMocker\Mocker::mockClassDependencies(App\BasePresenter::class);
22+
```
23+
24+
### Magic
25+
26+
Methods in BasePresenter:
27+
```
28+
$basePresenter->shouldReceive('add')->andReturn(1);
29+
```
30+
31+
Accessing dependencies of BasePresenter and setting up Mockery logic.
32+
33+
#### Private property
34+
```
35+
Spamer\DependencyMocker\Mocker::getProperty(
36+
App\BasePresenter::class,
37+
'articleModel',
38+
$this->articleModel
39+
)
40+
->shouldReceive('save')->once();
41+
```
42+
43+
#### Public property
44+
```
45+
$basePresenter->articleModel->shouldReceive('save')->once();
46+
```

composer.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "spamer/dependency-mocker",
3+
"type": "library",
4+
"description": "Loads dependencies to mocked classes by Mockery for Nette Framework.",
5+
"keywords": ["nette", "mockery", "dependency"],
6+
"homepage": "https://github.com/VBoss/DependencyMocker",
7+
"license": ["BSD-3-Clause", "GPL-2.0", "GPL-3.0"],
8+
"authors": [
9+
{
10+
"name": "Václav Čevela",
11+
"homepage": "https://github.com/VBoss/"
12+
}
13+
],
14+
"require": {
15+
"mockery/mockery": "0.9.*",
16+
"nette/di": "2.3.*"
17+
},
18+
"require-dev": {
19+
"nette/tester": "~1.6"
20+
},
21+
"autoload": {
22+
"classmap": [
23+
"src/"
24+
]
25+
},
26+
"autoload-dev": {
27+
"classmap": [
28+
"tests/"
29+
]
30+
}
31+
}
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
<?php
2+
3+
namespace Spamer\DependencyMocker;
4+
5+
use Nette;
6+
use Mockery;
7+
8+
class Mocker
9+
{
10+
/** @var array */
11+
public static $bannedClasses;
12+
13+
/** @var \ReflectionClass */
14+
private static $reflectedClass;
15+
16+
/** @var Mockery\Mock */
17+
private static $mockedClass;
18+
19+
/**
20+
* @param string $className
21+
* @return \ReflectionClass|\stdClass
22+
*/
23+
public static function mockClassDependencies($className)
24+
{
25+
self::$reflectedClass = new \ReflectionClass($className);
26+
self::$mockedClass = Mockery::mock($className);
27+
28+
self::mockInjectedMethods($className);
29+
self::mockInjectedProperties();
30+
self::mockConstructorDependencies($className);
31+
32+
return self::$mockedClass;
33+
}
34+
35+
36+
/**
37+
* @param string $className
38+
*/
39+
private static function mockInjectedMethods($className)
40+
{
41+
foreach (self::$reflectedClass->getMethods() as $method) {
42+
if (substr($method->getName(), 0, 6) === 'inject') {
43+
self::mockDependenciesFromMethod($className, $method->getName());
44+
}
45+
}
46+
}
47+
48+
49+
private static function mockInjectedProperties()
50+
{
51+
/** @var \ReflectionProperty $property */
52+
foreach (self::$reflectedClass->getProperties() as $property) {
53+
if (
54+
Nette\DI\PhpReflection::parseAnnotation($property, 'inject') !== NULL
55+
||
56+
Nette\DI\PhpReflection::parseAnnotation($property, 'autowire') !== NULL
57+
) {
58+
if ($mockedParameterClass = Nette\DI\PhpReflection::parseAnnotation($property, 'var')) {
59+
$mockedParameterClass = Nette\DI\PhpReflection::expandClassName(
60+
$mockedParameterClass,
61+
Nette\DI\PhpReflection::getDeclaringClass($property)
62+
);
63+
}
64+
self::setProperty($mockedParameterClass, $property);
65+
}
66+
}
67+
}
68+
69+
70+
/**
71+
* @param string $className
72+
*/
73+
private static function mockConstructorDependencies($className)
74+
{
75+
self::mockDependenciesFromMethod($className, '__construct');
76+
}
77+
78+
79+
/**
80+
* @param string $className
81+
* @param string $methodName
82+
*/
83+
private static function mockDependenciesFromMethod($className, $methodName)
84+
{
85+
$reflectionMethod = new \ReflectionMethod($className, $methodName);
86+
$parameters = $reflectionMethod->getParameters();
87+
88+
/** @var \ReflectionParameter $parameter */
89+
foreach ($parameters as $parameter) {
90+
if ($parameter->getClass()) {
91+
$parameterClass = $parameter->getClass()->getName();
92+
self::setProperty($parameterClass, $parameter);
93+
}
94+
}
95+
}
96+
97+
98+
/**
99+
* @param array $bannedClasses
100+
*/
101+
public static function setBannedClasses($bannedClasses)
102+
{
103+
self::$bannedClasses = $bannedClasses;
104+
}
105+
106+
107+
/**
108+
* @param string $className
109+
* @param \ReflectionParameter|\ReflectionProperty $class
110+
*/
111+
private static function setProperty($className, $class)
112+
{
113+
if ( ! in_array($className, self::$bannedClasses) && $class->getDeclaringClass()->hasProperty($class->getName())) {
114+
$mockedParameter = Mockery::mock($className);
115+
$property = new \ReflectionProperty($class->getDeclaringClass()->getName(), $class->getName());
116+
$property->setAccessible(TRUE);
117+
$property->setValue(self::$mockedClass, $mockedParameter);
118+
}
119+
}
120+
121+
122+
/**
123+
* @param string $class
124+
* @param string $property
125+
* @param object $object
126+
* @return mixed
127+
*/
128+
public static function getProperty($class, $property, $object)
129+
{
130+
$property = new \ReflectionProperty($class, $property);
131+
$property->setAccessible(TRUE);
132+
return $property->getValue($object);
133+
}
134+
}

0 commit comments

Comments
 (0)