Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Spamercz committed Dec 3, 2015
1 parent 6ea20dc commit e309ba9
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 1 deletion.
4 changes: 4 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.gitattributes export-ignore
.gitignore export-ignore
docs export-ignore
tests export-ignore
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
vendor
composer.lock
46 changes: 45 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,46 @@
# DependencyMocker
Loads dependencies to mocked class in Nette Framework environment.
Loads dependencies to mocked classes by Mockery for Nette Framework.

## Usage

### Set up

Banned Classes

Data entities, classes with different implementations of mockery magic (e.g. `__getStatic()`) etc.

```
Spamer\DependencyMocker\Mocker::setBannedClasses([
App\Entity\BaseEntity::class,
App\GetStatic::class,
]);
```

### Mock Class
```
$basePresenter = Spamer\DependencyMocker\Mocker::mockClassDependencies(App\BasePresenter::class);
```

### Magic

Methods in BasePresenter:
```
$basePresenter->shouldReceive('add')->andReturn(1);
```

Accessing dependencies of BasePresenter and setting up Mockery logic.

#### Private property
```
Spamer\DependencyMocker\Mocker::getProperty(
App\BasePresenter::class,
'articleModel',
$this->articleModel
)
->shouldReceive('save')->once();
```

#### Public property
```
$basePresenter->articleModel->shouldReceive('save')->once();
```
31 changes: 31 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"name": "spamer/dependency-mocker",
"type": "library",
"description": "Loads dependencies to mocked classes by Mockery for Nette Framework.",
"keywords": ["nette", "mockery", "dependency"],
"homepage": "https://github.com/VBoss/DependencyMocker",
"license": ["BSD-3-Clause", "GPL-2.0", "GPL-3.0"],
"authors": [
{
"name": "Václav Čevela",
"homepage": "https://github.com/VBoss/"
}
],
"require": {
"mockery/mockery": "0.9.*",
"nette/di": "2.3.*"
},
"require-dev": {
"nette/tester": "~1.6"
},
"autoload": {
"classmap": [
"src/"
]
},
"autoload-dev": {
"classmap": [
"tests/"
]
}
}
134 changes: 134 additions & 0 deletions src/Spamer/DependencyMocker/Mocker.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
<?php

namespace Spamer\DependencyMocker;

use Nette;
use Mockery;

class Mocker
{
/** @var array */
public static $bannedClasses;

/** @var \ReflectionClass */
private static $reflectedClass;

/** @var Mockery\Mock */
private static $mockedClass;

/**
* @param string $className
* @return \ReflectionClass|\stdClass
*/
public static function mockClassDependencies($className)
{
self::$reflectedClass = new \ReflectionClass($className);
self::$mockedClass = Mockery::mock($className);

self::mockInjectedMethods($className);
self::mockInjectedProperties();
self::mockConstructorDependencies($className);

return self::$mockedClass;
}


/**
* @param string $className
*/
private static function mockInjectedMethods($className)
{
foreach (self::$reflectedClass->getMethods() as $method) {
if (substr($method->getName(), 0, 6) === 'inject') {
self::mockDependenciesFromMethod($className, $method->getName());
}
}
}


private static function mockInjectedProperties()
{
/** @var \ReflectionProperty $property */
foreach (self::$reflectedClass->getProperties() as $property) {
if (
Nette\DI\PhpReflection::parseAnnotation($property, 'inject') !== NULL
||
Nette\DI\PhpReflection::parseAnnotation($property, 'autowire') !== NULL
) {
if ($mockedParameterClass = Nette\DI\PhpReflection::parseAnnotation($property, 'var')) {
$mockedParameterClass = Nette\DI\PhpReflection::expandClassName(
$mockedParameterClass,
Nette\DI\PhpReflection::getDeclaringClass($property)
);
}
self::setProperty($mockedParameterClass, $property);
}
}
}


/**
* @param string $className
*/
private static function mockConstructorDependencies($className)
{
self::mockDependenciesFromMethod($className, '__construct');
}


/**
* @param string $className
* @param string $methodName
*/
private static function mockDependenciesFromMethod($className, $methodName)
{
$reflectionMethod = new \ReflectionMethod($className, $methodName);
$parameters = $reflectionMethod->getParameters();

/** @var \ReflectionParameter $parameter */
foreach ($parameters as $parameter) {
if ($parameter->getClass()) {
$parameterClass = $parameter->getClass()->getName();
self::setProperty($parameterClass, $parameter);
}
}
}


/**
* @param array $bannedClasses
*/
public static function setBannedClasses($bannedClasses)
{
self::$bannedClasses = $bannedClasses;
}


/**
* @param string $className
* @param \ReflectionParameter|\ReflectionProperty $class
*/
private static function setProperty($className, $class)
{
if ( ! in_array($className, self::$bannedClasses) && $class->getDeclaringClass()->hasProperty($class->getName())) {
$mockedParameter = Mockery::mock($className);
$property = new \ReflectionProperty($class->getDeclaringClass()->getName(), $class->getName());
$property->setAccessible(TRUE);
$property->setValue(self::$mockedClass, $mockedParameter);
}
}


/**
* @param string $class
* @param string $property
* @param object $object
* @return mixed
*/
public static function getProperty($class, $property, $object)
{
$property = new \ReflectionProperty($class, $property);
$property->setAccessible(TRUE);
return $property->getValue($object);
}
}

0 comments on commit e309ba9

Please sign in to comment.