PHPUnit - Mockery::mock vs Mockery::namedMocks - php

I'm writing PHPUnit Test with Mockery, (PHP v5.6.32, PHPUnit 3.7.21, Mockery dev-master) and found something which I can't understand about using Mockery::mock and Mockery::namedMocks.
My code is below, and the questions are:
Am I correct to use in LegendTest.php the Mockery::namedMock() instead of Mockery::mock() for SignalsCollection object?
Regarding to documentation about namedMock, I expect that frist argument is the Class name (SignalsCollection) and the second argument should be the extends statement (\ArrayObject) - but in my case I'm getting an error: Mockery\Exception\BadMethodCallException : Received Charts\SignalsCollection::getIterator(), but no expectations were specified, so I'm giving only one argument and this works fine. Why? What am I doing wrong? I'm confused.
Did I missed something in this test case or should I do something different to make tests better?
Signal.php:
class Signal
{
protected $id = 0;
protected $colName = '';
protected $tableName = '';
public function getId()
{
return $this->id;
}
public function setColName($colName)
{
$this->colName = $colName;
return $this;
}
public function setTableName($tableName)
{
$this->tableName = $tableName;
return $this;
}
}
SignalsCollection.php:
class SignalsCollection extends \ArrayObject
{
}
Legend.php
class Legend
{
protected $signalsCollection = null;
protected $graphModel = null;
public function __construct(SignalsCollection $signalsCollection, GraphModel $graphModel)
{
$this->signalsCollection = $signalsCollection;
$this->graphModel = $graphModel;
}
public function getSignalsCollection()
{
return $this->signalsCollection;
}
public function removeSignal(Signal $signal)
{
foreach ($this->signalsCollection as $key => $item) {
if ($item->getId() === $signal->getId()) {
$this->signalsCollection->offsetUnset($key);
break;
}
}
}
}
LegendTest.php:
class LegendTest extends \PHPUnit_Framework_TestCase
{
protected function tearDown()
{
parent::tearDown();
Mockery::close();
}
public function testRemoveSignal()
{
$testSignal = Mockery::mock('\Charts\Signal')
->shouldReceive('setColName', 'setTableName')
->andReturn(Mockery::self())
->mock();
$testSignal
->setColName('testColumnName')
->setTableName('testTableName');
$testSignalSecond = Mockery::mock('\Charts\Signal')
->shouldReceive('setId', 'setColName', 'setTableName')
->andReturn(Mockery::self())
->mock();
$testSignalSecond
->setId(1)
->setColName('testColumnName')
->setTableName('testTableName');
$signalsCollection = Mockery::namedMock('\Charts\SignalsCollection')
->shouldReceive('append', 'offsetUnset')
->andReturn(Mockery::self())
->mock();
$signalsCollection
->append($testSignal)
->append($testSignalSecond);
$legend = new Legend($signalsCollection, Mockery::mock('\Charts\GraphModel'));
$this->assertEquals($signalsCollection, $legend->getSignalsCollection());
$legend->removeSignal($testSignalSecond);
$signalsCollection->offsetUnset(1);
$this->assertEquals( $signalsCollection, $legend->getSignalsCollection() );
}
}

Related

Fatal error after declaring function abstract

I have a problem with an error I am getting that says:
Class Car contains 1 abstract method and must therefore be decla
red abstract or implement the remaining methods (Car::accelerate) in C:\xampp
\htdocs\php\learn_php_oop\Car.php on line 58.
This is the code in two files I am using:
Car.php
<?php
/**
* represents generic properties and methods for any type of car
*/
class Car
{
protected $colour, $doorNumber, $fuelType, $rightHandDrive, $accelerate;
public function __construct($rightHandDrive = true)
{
$this->rightHandDrive = $rightHandDrive;
}
public function getColour()
{
return $this->colour;
}
public function setColour($colour)
{
$this->colour = $colour;
}
public function getDoorNumber()
{
return $this->doorNumber;
}
public function setDoorNumber($doorNumber)
{
$this->doorNumber = $doorNumber;
}
public function getFuelType()
{
return $this->fuelType;
}
public function setFuelType($fuelType)
{
$this->fuelType = $fuelType;
}
public function getRightHandDrive()
{
return $this->rightHandDrive;
}
public function setRightHandDrive($rightHandDrive)
{
$this->rightHandDrive = $rightHandDrive;
}
abstract protected function accelerate();
}
?>
Sport_car.php
<?php
include ('Car.php');
/**
* represents sport cars
*/
class Sport_car extends Car
{
public function accelerate()
{
$this->accelerate = 5;
}
}
?>
I have spent some time trying to figure out why this is happening but I just do not know why? Please help.
It's an OOP problem, in your case you must declare your Car Object as Abstract like this :
<?php
/**
* represents generic properties and methods for any type of car
*/
abstract class Car
{
protected $colour, $doorNumber, $fuelType, $rightHandDrive, $accelerate;
public function __construct($rightHandDrive = true)
{
$this->rightHandDrive = $rightHandDrive;
}
public function getColour()
{
return $this->colour;
}
public function setColour($colour)
{
$this->colour = $colour;
}
public function getDoorNumber()
{
return $this->doorNumber;
}
public function setDoorNumber($doorNumber)
{
$this->doorNumber = $doorNumber;
}
public function getFuelType()
{
return $this->fuelType;
}
public function setFuelType($fuelType)
{
$this->fuelType = $fuelType;
}
public function getRightHandDrive()
{
return $this->rightHandDrive;
}
public function setRightHandDrive($rightHandDrive)
{
$this->rightHandDrive = $rightHandDrive;
}
abstract protected function accelerate();
}
?>
Explanations :
A class wich is extended with at least one abstract method in it has to be defined as abstract itself, otherwise you'll get an error

PHP: Get Acces To Private Variable In Class

I've been doing a project in PHP for the last few hours and I have encountered into a problem.
The problem is I don't know how to access private variables in a class and I can't find it online.
Example:
<?php
class Example{
private $age;
public function __construct() {
$age = 14;
$this->checkAge();
}
private function checkAge() {
if($this->$age > 12)
echo "welcome!";
}
}
$boy = new Example();
?>
As far as I know, I should be able to access the variable with $this->$age but it isn't working.
Thank you.
EDIT: Got it working with help of the awesome stackoverflooooooooow community, this is how a working one looks.
<?php
class Example{
private $age;
public function __construct() {
$this->age = 14;
$this->checkAge();
}
private function checkAge() {
if($this->age > 12)
echo "welcome!";
}
}
$boy = new Example();
?>
Look at this approach.
first: create Entity that stores and retrieves data inside of private $attributes array, and with magic __set(), __get() You can also do like: $object->variable = 123
second: extend Entity with Human class and add some function specific to child class (for example hasValidAge()):
<?php
class Entity {
private $attributes;
public function __construct($attributes = []) {
$this->setAttributes($attributes);
}
public function setAttribute($key, $value) {
$this->attributes[$key] = $value;
return $this;
}
public function setAttributes($attributes = []) {
foreach($attributes AS $key => $value) {
$this->setAttribute($key, $value);
}
}
public function getAttribute($key, $fallback = null) {
return (isset($this->attributes[$key]))?
$this->attributes[$key] : $fallback;
}
public function __get($key) {
return $this->getAttribute($key);
}
public function __set($key, $value) {
$this->setAttribute($key, $value);
}
}
class Human extends Entity {
public function __construct($attributes = []) {
$this->setAttributes($attributes);
$this->checkAge();
}
public function hasValidAge() {
return ($this->getAttribute('age') > 12)? true : false;
}
}
$boy = new Human(['name' => 'Mark', 'age' => 14]);
if($boy->hasValidAge()) {
echo "Welcome ".$boy->name."!";
}
?>
p.s. I've removed echo "Welcome!" part from constructor because it's not cool to do echo from model object, in our example Human is model of Entity.

How to user ThrowException matcher in PHPSpec?

I have problem in using ExceptionMatcher...My example spec:
class DescribeBall extends \PHPSpec\Context {
private $_ball = null;
function before() {
$this->_ball = $this->spec(new Ball);
}
function itShouldHaveStatusRolledOnRoll() {
$this->_ball->roll();
$this->_ball->getStatus()->should->be('Rolled');
}
function itShouldThrowException() {
$this->_ball->getException()->should->throwException('Exception','Error');
}
}
My example class
class Ball {
private $status = null;
public function roll() {
$this->status = 'Rolled';
}
public function getStatus() {
return $this->status;
}
public function getException() {
throw new Exception('Error');
}
}
Anyone used this matcher with success?
$this->_ball->getException()->should->throwException('Exception','Error');
Thanks to my colleagues:
"The last time I looked at it, it used closures (unless Marcello changed it meanwhile) it should still work like this":
function itShouldThrowException() {
$ball = $this->_ball;
$this->spec(function() use ($ball) {
$ball->getException();
})->should->throwException('Exception','Error');
}

get set properties in php

I'm from the C# environment and I'm starting to learn PHP in school.
I'm used to set my properties in C# like this.
public int ID { get; set; }
What's the equivalent to this in php?
Thanks.
There is none, although there are some proposals for implementing that in future versions.
For now you unfortunately need to declare all getters and setters by hand.
private $ID;
public function setID($ID) {
$this->ID = $ID;
}
public function getID() {
return $this->ID;
}
for some magic (PHP likes magic), you can look up __set and __get magic methods.
Example
class MyClass {
private $ID;
private function setID($ID) {
$this->ID = $ID;
}
private function getID() {
return $this->ID;
}
public function __set($name,$value) {
switch($name) { //this is kind of silly example, bt shows the idea
case 'ID':
return $this->setID($value);
}
}
public function __get($name) {
switch($name) {
case 'ID':
return $this->getID();
}
}
}
$object = new MyClass();
$object->ID = 'foo'; //setID('foo') will be called
Thanks for your answers everyone. It helped me to create something like this:
In my parent class:
public function __get($name){
if (ObjectHelper::existsMethod($this,$name)){
return $this->$name();
}
return null;
}
public function __set($name, $value){
if (ObjectHelper::existsMethod($this,$name))
$this->$name($value);
}
ObjectHelper::existsMethod is a method which just check if given protected method exists.
private $_propertyName = null;
protected function PropertyName($value = ""){
if (empty($value)) // getter
{
if ($this-> _propertyName != null)
return $this->_propertyName;
}
else // setter
{
$this-> _propertyName = $value;
}
return null;
}
So I can use something like this in any class:
$class = new Class();
$class->PropertyName = "test";
echo $class->PropertyName;
I was inspired by C# :)
What do you think about this, guys?
Here is my ObjectHelper if someone would like to use it:
namespace Helpers;
use ReflectionMethod;
class ObjectHelper {
public static function existsMethod($obj, $methodName){
$methods = self::getMethods($obj);
$neededObject = array_filter(
$methods,
function ($e) use($methodName) {
return $e->Name == $methodName;
}
);
if (is_array($neededObject))
return true;
return false;
}
public static function getMethods($obj){
$var = new \ReflectionClass($obj);
return $var->getMethods(ReflectionMethod::IS_PROTECTED);
}
}
Mchi is right, but there is another way of doing it by using single function
private $ID;
public function ID( $value = "" )
{
if( empty( $value ) )
return $this->ID;
else
$this->ID = $value;
}
But yeah this approach is pretty much inline with what you do in c#. but this is only an alternative
Or try using php's __set and __get in your class more info here
http://php.net/manual/en/language.oop5.overloading.php
Another exampled using Variable function name
class MyClass {
private $ID;
protected $ID2;
private function setID($ID) {
$this->ID = $ID;
}
private function getID() {
return $this->ID;
}
private function setID2($ID2) {
$this->ID2 = $ID2;
}
private function getID2() {
return $this->ID2;
}
public function __set($name,$value) {
$functionname='set'.$name;
return $this->$functionname($value);
}
public function __get($name) {
$functionname='get'.$name;
return $this->$functionname();
}
}
$object = new MyClass();
$object->ID = 'foo'; //setID('foo') will be called
$object->ID2 = 'bar'; //setID2('bar') will be called
private $ID;
public function getsetID($value = NULL)
{
if ($value === NULL) {
return $this->ID;
} else {
$this->ID = $value;
}
}
I know I am a bit late to the party on this question, but I had the same question/thought myself. As a C# developer who does PHP, when the job requires, I want to have a simple way to create properties just I would be able to in C#.
I whipped up a first draft this afternoon which allows you to create the backing fields and specify their accessors or have pure accessors with no backing field. I will update my answer as the code evolves and provide a link when I get it to the state where it can be imported as a composer package.
For simplicity, I created the functionality as a PHP trait so you can drop it in to any class you want instead of having to extend a base class. Eventually I hope to extend this functionality to discern between external public calls to the properties and protected/private calls.
Here is the code for the trait itself:
trait PropertyAccessorTrait
{
private static $__propertyAccessors = [];
/* #property string $__propertyPrefix */
public function __get($name)
{
$this->__populatePropertyAcessors($name);
return $this->__performGet($name);
}
public function __set($name, $value)
{
$this->__populatePropertyAcessors($name);
$this->__performSet($name, $value);
}
public function __isset($name)
{
// TODO: Implement __isset() method.
}
public function __unset($name)
{
// TODO: Implement __unset() method.
}
protected function __getBackingFieldName($name)
{
if (property_exists(self::class, '__propertyPrefix')) {
$prefix = $this->__propertyPrefix;
} else {
$prefix = '';
}
return $prefix . $name;
}
protected function __canget($name)
{
$accessors = $this->__getPropertyAccessors($name);
return $accessors !== null && isset($accessors['get']);
}
protected function __canset($name)
{
$accessors = $this->__getPropertyAccessors($name);
return $accessors !== null && isset($accessors['set']);
}
protected function __performGet($name)
{
if (!$this->__canget($name)) {
throw new \Exception('Getter not allowed for property: ' . $name);
}
$accessors = $this->__getPropertyAccessors($name)['get'];
/* #var \ReflectionMethod $method */
$method = $accessors['method'];
if (!empty($method)) {
return $method->invoke($this);
}
return $this->{$this->__getBackingFieldName($name)};
}
protected function __performSet($name, $value)
{
if (!$this->__canset($name)) {
throw new \Exception('Setter not allowed for property: ' . $name);
}
$accessors = $this->__getPropertyAccessors($name)['set'];
/* #var \ReflectionMethod $method */
$method = $accessors['method'];
if (!empty($method)) {
return $method->invoke($this, $value);
}
$this->{$this->__getBackingFieldName($name)} = $value;
}
protected function __getPropertyAccessors($name)
{
return isset(self::$__propertyAccessors[$name])
? self::$__propertyAccessors[$name]
: null
;
}
protected function __getAccessorsFromDocBlock($docblock)
{
$accessors = [];
if (!empty(trim($docblock))) {
$doclines = null;
if (!empty($docblock)) {
$doclines = explode("\n", $docblock);
}
if (!empty($doclines)) {
foreach ($doclines as $line) {
if (preg_match('/#(get|set)\\s+(public|private|protected)/', $line, $matches)) {
$accessors[$matches[1]]['visibility'] = $matches[2];
}
}
}
}
return $accessors;
}
protected function __populatePropertyAcessors($name)
{
if ($this->__getPropertyAccessors($name) !== null) return;
try {
$property = new \ReflectionProperty(self::class, $this->__getBackingFieldName($name));
} catch (\ReflectionException $ex) {
$property = null;
}
$accessors = [];
if ($property != null) {
$accessors = $this->__getAccessorsFromDocBlock($property->getDocComment());
}
try {
$methodName = 'get' . ucfirst($name);
$method = new \ReflectionMethod(self::class, $methodName);
$method->setAccessible(true);
$accessors = array_merge($accessors, $this->__getAccessorsFromDocBlock($method->getDocComment()));
} catch (\ReflectionException $ex) {
$method = null;
}
if ($method !== null || isset($accessors['get'])) {
$accessors['get']['method'] = $method;
}
try {
$methodName = 'set' . ucfirst($name);
$method = new \ReflectionMethod(self::class, $methodName);
$method->setAccessible(true);
$accessors = array_merge($accessors, $this->__getAccessorsFromDocBlock($method->getDocComment()));
} catch (\ReflectionException $ex) {
$method = null;
}
if ($method !== null || isset($accessors['set'])) {
$accessors['set']['method'] = $method;
}
self::$__propertyAccessors[$name] = $accessors;
}
}
Here is a quick unit test I created using the Codeception format:
<?php
class PropertyAssesorTraitTestClass
{
use PropertyAccessorTrait;
private $__propertyPrefix = '_';
/**
* #get public
* #set public
*/
private $_integer = 1;
/**
* #get public
*/
private $_getonly = 100;
/**
* #set public
*/
private $_setonly;
private $_customDoubler;
private function getCustomDoubler()
{
return $this->_customDoubler * 2;
}
private function setCustomDoubler($value)
{
$this->_customDoubler = $value * 2;
}
public $publicField = 1234;
/**
* #return int
* #get public
*/
private function getPureAccessor()
{
return $this->publicField;
}
/**
* #param $value
* #set public
*/
private function setPureAccessor($value)
{
$this->publicField = $value;
}
private $_purePrivate = 256;
}
$I = new UnitTester($scenario);
$I->wantTo('Ensure properties are accessed correctly');
$instance = new PropertyAssesorTraitTestClass();
$I->assertSame(1, $instance->integer);
$instance->integer = 2;
$I->assertSame(2, $instance->integer);
$instance->integer = $instance->integer + 1;
$I->assertSame(3, $instance->integer);
$instance->integer++;
$I->assertSame(4, $instance->integer);
$I->assertSame(100, $instance->getonly);
$I->expectException('Exception', function () use ($instance) { $instance->getonly = 50; });
$instance->setonly = 50;
$I->expectException('Exception', function () use ($instance) { $a = $instance->setonly; });
$instance->customDoubler = 100;
$I->assertSame(400, $instance->customDoubler);
$I->assertSame(1234, $instance->publicField);
$instance->pureAccessor = 1000;
$I->assertSame(1000, $instance->publicField);
$instance->publicField = 1234;
$I->assertSame(1234, $instance->publicField);
$I->assertSame(1234, $instance->pureAccessor);
$I->expectException('Exception', function () use ($instance) { return $instance->purePrivate; });
I like to use this pattern:
class foo
{
//just add p as prefix to be different than method name.
protected $pData;
public funtion __construct() {}
public funtion __destruct() {}
public funtion __clone() {}
public function Data($value == "")
{
if ($value != "") {
$this->pData = $value;
}
return $this->pData;
}
}
$myVar = new foo();
//for SET
$myVar->Data("A Value");
//for GET
$item = $myVar->Data();
class MyClass
{
private $name = null;
public function __construct($name = null)
{
$this->name = $name;
}
public function __set($name, $value)
{
if (property_exists($this, $name)) {
$this->name = $value;
}
return $this;
}
public function __get($name)
{
if (property_exists($this, $name)) {
return $this->$name;
}
return null;
}
}
this is PHP ; you don't need get set
class MyClass {
public $ID;
}
$object = new MyClass();
$object->ID = 'foo';
echo $object->ID;
will work

The correct way of doing delegates or callbacks in PHP

I need to implement the following pattern in php:
class EventSubscriber
{
private $userCode;
public function __construct(&$userCode) { $this->userCode = &$userCode; }
public function Subscribe($eventHandler) { $userCode[] = $eventHandler; }
}
class Event
{
private $subscriber;
private $userCode = array();
public function __construct()
{
$this->subscriber = new Subscriber($this->userCode)
}
public function Subscriber() { return $this->subscriber; }
public function Fire()
{
foreach ($this->userCode as $eventHandler)
{
/* Here i need to execute $eventHandler */
}
}
}
class Button
{
private $eventClick;
public function __construct() { $this->eventClick = new Event(); }
public function EventClick() { return $this->eventClick->Subscriber(); }
public function Render()
{
if (/* Button was clicked */) $this->eventClick->Fire();
return '<input type="button" />';
}
}
class Page
{
private $button;
// THIS IS PRIVATE CLASS MEMBER !!!
private function ButtonClickedHandler($sender, $eventArgs)
{
echo "button was clicked";
}
public function __construct()
{
$this->button = new Button();
$this->button->EventClick()->Subscribe(array($this, 'ButtonClickedHandler'));
}
...
}
what is the correct way to do so.
P.S.
I was using call_user_func for that purpose and believe it or not it was able to call private class members, but after few weeks of development i've found that it stopped working. Was it a bug in my code or was it some something else that made me think that 'call_user_func' is able call private class functions, I don't know, but now I'm looking for a simple, fast and elegant method of safely calling one's private class member from other class. I'm looking to closures right now, but have problems with '$this' inside closure...
Callbacks in PHP aren't like callbacks in most other languages. Typical languages represent callbacks as pointers, whereas PHP represents them as strings. There's no "magic" between the string or array() syntax and the call. call_user_func(array($obj, 'str')) is syntactically the same as $obj->str(). If str is private, the call will fail.
You should simply make your event handler public. This has valid semantic meaning, i.e., "intended to be called from outside my class."
This implementation choice has other interesting side effects, for example:
class Food {
static function getCallback() {
return 'self::func';
}
static function func() {}
static function go() {
call_user_func(self::getCallback()); // Calls the intended function
}
}
class Barf {
static function go() {
call_user_func(Food::getCallback()); // 'self' is interpreted as 'Barf', so:
} // Error -- no function 'func' in 'Barf'
}
Anyway, if someone's interested, I've found the only possible solution via ReflectionMethod. Using this method with Php 5.3.2 gives performance penalty and is 2.3 times slower than calling class member directly, and only 1.3 times slower than call_user_func method. So in my case it is absolutely acceptable. Here's the code if someone interested:
class EventArgs {
}
class EventEraser {
private $eventIndex;
private $eventErased;
private $eventHandlers;
public function __construct($eventIndex, array &$eventHandlers) {
$this->eventIndex = $eventIndex;
$this->eventHandlers = &$eventHandlers;
}
public function RemoveEventHandler() {
if (!$this->eventErased) {
unset($this->eventHandlers[$this->eventIndex]);
$this->eventErased = true;
}
}
}
class EventSubscriber {
private $eventIndex;
private $eventHandlers;
public function __construct(array &$eventHandlers) {
$this->eventIndex = 0;
$this->eventHandlers = &$eventHandlers;
}
public function AddEventHandler(EventHandler $eventHandler) {
$this->eventHandlers[$this->eventIndex++] = $eventHandler;
}
public function AddRemovableEventHandler(EventHandler $eventHandler) {
$this->eventHandlers[$this->eventIndex] = $eventHandler;
$result = new EventEraser($this->eventIndex++, $this->eventHandlers);
return $result;
}
}
class EventHandler {
private $owner;
private $method;
public function __construct($owner, $methodName) {
$this->owner = $owner;
$this->method = new \ReflectionMethod($owner, $methodName);
$this->method->setAccessible(true);
}
public function Invoke($sender, $eventArgs) {
$this->method->invoke($this->owner, $sender, $eventArgs);
}
}
class Event {
private $unlocked = true;
private $eventReceiver;
private $eventHandlers;
private $recursionAllowed = true;
public function __construct() {
$this->eventHandlers = array();
}
public function GetUnlocked() {
return $this->unlocked;
}
public function SetUnlocked($value) {
$this->unlocked = $value;
}
public function FireEventHandlers($sender, $eventArgs) {
if ($this->unlocked) {
//защита от рекурсии
if ($this->recursionAllowed) {
$this->recursionAllowed = false;
foreach ($this->eventHandlers as $eventHandler) {
$eventHandler->Invoke($sender, $eventArgs);
}
$this->recursionAllowed = true;
}
}
}
public function Subscriber() {
if ($this->eventReceiver == null) {
$this->eventReceiver = new EventSubscriber($this->eventHandlers);
}
return $this->eventReceiver;
}
}
As time passes, there are new ways of achieving this.
Currently PSR-14 is drafted to handle this use case.
So you might find any of these interesting:
https://packagist.org/?query=psr-14

Categories