How to mock inner function in phpunit? - php

This is my Foo class
<?php
class FooClass
{
public function doFoo($total)
{
$gst = (($this->getTaxRate() / 100) * $total);
return $gst;
}
public function getTaxRate()
{
return 5;
}
}
And this is my test.
public function fooTest()
{
$mockedObj = $this->createMock(FooClass::class);
$mockedObj->expects($this->exactly(1))
->method('getTaxRate')
->will($this->returnValue(10));
$this->assertEquals(10, $mockedObj->doFoo(100));
}
Output:
Failed asserting that null matches expected 10.
I can see getTaxRate() function is not being mocked .It is also returning null instead of 5(default value). I am expecting getTaxRate() inside doFoo() to return the mock value i.e 10 else if I do not mock a getTaxRate, it should return 5.
Anything that I am missing here?

Related

Access the parent object of an object in PHP

This is my test code:
class Base
{
public $property;
public function method() {
return 456;
}
public function setProperty($value) {
$this->property = $value;
}
}
class Derived extends Base
{
public function method() {
return 789;
}
}
$derived = new Derived;
$derived->setProperty(123);
$base = getParentInstance($derived);
echo $base->property; // Should print 123
echo $base->method(); // Should print 456
Looking around I found a lot of stuff related but nothing direct to the point. I just need to cast an instance to an ancestor class. Is this even possible on PHP?
Up to now I came out with this wrong code that (I think) just instantiate a new Base class:
function getParentInstance($object)
{
$reflection = new ReflectionObject($object);
$parent_class = $reflection->getParentClass();
return $parent_class->newInstanceWithoutConstructor();
}
Another complication is I can only modify Derived... Base is provided by an external framework.
Addendum
Here is the proof what I'm requesting is not absurd. Same code in C++:
class Base
{
public:
int property;
int method() {
return 456;
}
void setProperty(int value) {
this->property = value;
}
};
class Derived: public Base
{
public:
int method() {
return 789;
}
};
#include <iostream>
int main()
{
Derived *derived = new Derived;
derived->setProperty(123);
Base *base = (Base *) derived; // Is **this** possible in PHP?
std::cout << base->property; // It prints 123
std::cout << base->method(); // It prints 456
return 0;
}
As many mentioned, you shouldn't do it, and technically speaking you can't.
You can simulate the behaviour to get the results you expect as following:
class Derived extends Base
{
protected $isProxy = false;
public function method() {
return $this->isProxy ? parent::method() : 'def';
}
/**
* not really a parent. The same class, which behave like a parent in this specific case
*/
public function getParent()
{
$this->isProxy = true;
$base = clone $this;
$this->isProxy = false;
return $base;
}
}
$derived = new Derived;
$derived->setProperty(123);
$base = $derived->getParent();
echo $base->property; // prints 123
echo $base->method(); // prints 456
EDIT:
a simplified example of what else you can do:
function getParentInstance($child) {
$base = new Base();
$base->property = $child->property;
return $base;
}
This works with public properties only.
Private/Protected properties should be accessed/assigned using Reflection.
Just figured I would put this here since it sort of answers the question. While there is not an instantiated Base object you still have access to parent data through php's parent.
I am not 100% sure what the attempt here is but you could use it like
//No changes to Base
class Derived extends Base {
public function method($p=false) {//Adding a flag
if($p){// true mean you want the parent method
return parent::method(); //Use parent:: to call that method
} else { //False do your own thing
return 'def';
}
}
}
$derived = new Derived;
$derived->setProperty(123);
echo $derived->property; // Print 123
echo $derived->method(); // Prints def
echo $derived->method(false); // Prints def
echo $derived->method(true); // Prints 456
This is strange but one way to at least get the expectations.
Also, the easiest way is to not overwrite your parent method when parent and child function differently.
//No changes to Base
class Derived extends Base {
public function child_method() {
return 'def';
}
}
$derived = new Derived;
$derived->setProperty(123);
echo $derived->property; // Print 123
echo $derived->method(); // Prints 456
echo $derived->child_method(false); // Prints def

How to save result OOP?

I have the following class:
class Algorithm {
public function __constructor($arr){
$this->arr = $arr;
}
public function handle(){
return $this->Q($this->arr[0]); // 1, 2, 3 etc
}
public function Q(){
return 2;
}
public function R(){
return 1;
}
}
I create some instances of class in loop:
foreach($arr as $key){
$objects[] = new Algorithm(["1", "2", "3"]);
}
So, I need to handle all values passed to Algorithm and return state execution. I mean save result from Q and R methods in class.
So in result I need to get so as:
$objects[0]->Q; //1
$objects[1]->Q; //2
$objects[0]->R; //1
$objects[1]->R; //2
After I need to pass result objects in another class B:
$nextHandle = new B($objects);
Where get others result of two functions:
class B {
public function go($objects[0]) {
return 1;
}
public function do($objects[0]) {
return 1;
}
}
In result also return values do()and go()
So, problem is that I don't know how to operate of instances of object and pass these for calculation in another class. Also how to save intermediate states of calculations, I mean methods in each class?
Also one of main thinking is how to pass object with all states in another instance of class, that inside I can get state of element passed object?

PHP Last Object of Method Chaining

In PHP using method chaining how would one go about supplying a functional call after the last method being called in the chain?
Also while using the same instance (see below). This would kill the idea of implementing a destructor.
The end result is a return value and functional call of private "insert()" from the defined chain properties (of course) without having to call it publicly, no matter of the order.
Note, if I echo (__toString) the methods together it would retrieve the final generated unique code which is normal behavior of casting a string.
Example below:
class object
{
private $data;
function __construct($name) {
// ... some other code stuff
}
private function fc($num) {
// some wicked code here
}
public function green($num) {
$this->data .= fc($num*10);
return $this;
}
public function red($num) {
$this->data .= fc($num*25);
return $this;
}
public function blue($num) {
$this->data .= fc($num*1);
return $this;
}
// how to get this baby to fire ?
private function insert() {
// inserting
file_put_content('test_code.txt', $this->data);
}
}
$tss = new object('index_elements');
$tss->blue(100)->green(200)->red(100); // chain 1
$tss->green(0)->red(100)->blue(0); // chain 2
$tss->blue(10)->red(80)->blue(10)->green(0); // chain 3
Chain 1, 2, and 3 would generated an unique code given all the values from the methods and supply an action, e.g. automatically inserting in DB or creating a file (used in this example).
As you can see no string setting or casting or echoing is taking place.
You could keep a list of things that needs to be initialised and whether they
have been so in this instance or not. Then check the list each time you use
one of the initialisation methods. Something like:
class O {
private $init = array
( 'red' => false
, 'green' => false
, 'blue' => false
);
private function isInit() {
$fin = true;
foreach($this->init as $in) {
$fin = $fin && $in;
}
return $fin;
}
public function green($n) {
$this->init['green'] = true;
if($this->isInit()) {
$this->insert();
}
}
public function red($n) {
$this->init['red'] = true;
if($this->isInit()) {
$this->insert();
}
}
public function blue($n) {
$this->init['blue'] = true;
if($this->isInit()) {
$this->insert();
}
}
private function insert() {
echo "whee\n";
}
}
But personally I think this would be more hassle then it's worth. Better imo
to expose your insert method and let the user of you code tell when the
initialisation is finished. So something that should be used like:
$o->red(1)->green(2)->blue(0)->insert();
-update-
If it's the case that it's impossible to predict what functions need to be called
you really do need to be explicit about it. I can't see a way around that. The reason
is that php really can't tell the difference between
$o1 = new A();
$o2 = $o1->stuff();
and
$o2 = (new A())->stuff();
In a language that allows overloading = I guess it would be possible but really
really confusing and generally not a good idea.
It is possible to move the explicit part so that it's not at the end of the call
chain, but I'm not sure if that would make you happier? It would also go against
your desire to not use another instance. It could look something like this:
class O {
public function __construct(InitO $ini) {
// Do stuff
echo "Whee\n";
}
}
class InitO {
public function red($n) {
return $this;
}
public function green($n) {
return $this;
}
public function blue($n) {
return $this;
}
}
$o = new O((new InitO())->red(10)->red(9)->green(7));
You can of course use just one instance by using some other way of wrapping
but the only ways I can think of right now would look a lot uglier.
Im with PeeHaa, this makes no sense! :)
Only chance to have something magically happen after the last chain was used (without being able to look into the future) is a Destructor/Shutdown function OR a manually cast/call to insert()
You can also decide to implement this statically without using objects.
<?php
class Object
{
private static $data;
public static function set($name)
{
// ... some other code stuff
}
private static function fc($num)
{
// some wicked code here
}
public static function green($num)
{
self::$data .= self::fc($num*10);
return new static;
}
public static function red($num)
{
self::$data .= self::fc($num*25);
return new static;
}
public static function blue($num) {
self::$data .= self::fc($num*1);
return new static;
}
// how to get this baby to fire ?
public static function insert()
{
// inserting
file_put_content('test_code.txt', self::$data);
}
}
//$tss = new object('index_elements');
$Object::set('index_elements')->blue(100)->green(200)->red(100)->insert(); // chain 1
$Object::set('index_elements')->green(0)->red(100)->blue(0)->insert(); // chain 2
$Object::set('index_elements')->blue(10)->red(80)->blue(10)->green(0)->insert(); // chain 3
?>
Ok let's see a code example
<?php
// map dummy class
class map
{
// __call magic method
public function __call($name, $args)
{
return $this;
}
}
// now we chain
$map = new map;
// let's find me
$map->start('here')
->go('right')
->then()
->turn('left')
->and('get water')
->dontEat()
->keep('going')
->youShouldSeeMe('smiling');
here we don't know what the last method would be and we need to trigger a kinda operation or event once we hit the end.
According to data structure we can call this the LIFO stack. (Last in first out)
so how did i solve this on PHP?
// i did some back tracing
... back to the __call function
function __call($name, $args)
{
$trace = debug_backtrace()[0];
$line = $trace['line'];
$file = $trace['file'];
$trace = null;
$getFile = file($file);
$file = null;
$getLine = trim($getFile[$line-1]);
$line = null;
$getFile = null;
$split = preg_split("/(->)($name)/", $getLine);
$getLine = null;
if (!preg_match('/[)](->)(\S)/', $split[1]) && preg_match('/[;]$/', $split[1]))
{
// last method called.
var_dump($name); // outputs: youShouldSeeMe
}
$split = null;
return $this;
}
And whoolla we can call anything once we hit the bottom.
*(Notice i use null once i am done with a variable, i come from C family where we manage memory ourselves)
Hope it helps you one way or the other.

Having trouble detecting 'return false'

I have a PHP class that can return FALSE.
For some weird reason, I am unable to detect the FALSE return.
I can detect any other return value without any trouble.
Dumbed down version....
error_reporting(E_ALL);
ini_set("display_errors", 1);
$run = new myClass();//class returns false
$response = $run->myMethod();
I've tested with the following...
!$response
!isset($response)
empty($response)
$response == false
$response === false
I'm unable to get any type of reaction for any of the conditions I'm familiar with.
If I set the return to 1 or ANYTHING other than false, $response will contain whatever the class returns.
It's not like this is my first day. (it's my 2nd).
I use return false; frequently and have never had any trouble until today.
Certainly I can fix this by returning something like 'wtf' and test for that condition, but I'd really like to figure out what I'm missing here.
Thanks for any ideas.
When you make a instance of your class it will always your return a object not the return of the construct.
<?php
class SomeClass
{
// construct function that will always return false
public function __construct()
{
return false;
}
}
class TestClass extends PHPUnit_Framework_TestCase
{
public function testReturn()
{
// check if this code returns false
$this->assertFalse(new SomeClass);
}
public function testAssert()
{
// Checks if the object return is actually of SomeClass
$this->assertInstanceOf('SomeClass', new SomeClass);
}
public function testReturnOfConstruct()
{
//checks the return of the construct
$object = new SomeClass;
$this->assertFalse($object->__construct());
}
}
Return of phpunit
phpunit --debug test3.php
PHPUnit 3.7.28 by Sebastian Bergmann.
Starting test 'TestClass::testReturn'.
F
Starting test 'TestClass::testAssert'.
.
Starting test 'TestClass::testReturnOfConstruct'.
.
Time: 7 ms, Memory: 5.25Mb
There was 1 failure:
1) TestClass::testReturn
Failed asserting that SomeClass Object () is false.
/var/www/test3.php:14
FAILURES!
Tests: 3, Assertions: 3, Failures: 1.
Are you trying to return false from within public function __construct() or public function MyClass()*? This won't work as the new MyClass() call will either trigger a PHP error, or return an instance of MyClass, which is never going to evaluate to false because it is an instance of an object and thus not false.
If your class does not need to be instantiated to function, you can create a static method to perform the logic you are trying to run like so:
<?php
class MyClass
{
const COLOUR_BLUE = 'blue';
public static function isSkyBlue()
{
if (isset($_POST['sky']) && $_POST['sky'] == self::COLOUR_BLUE) {
return true;
} else {
return false;
}
}
}
// Call doThings() statically to get its value
$response = MyClass::isSkyBlue();
if ($response === false) {
// Your logic goes here
}
Alternatively, if you are passing things to the constructor before it performs its logic, you can do the following:
<?php
class MyClass
{
const COLOUR_BLUE = 'blue';
protected $otherObject = null;
public function __construct($otherObject)
{
$this->otherObject = $otherObject;
}
public function isSkyBlue()
{
if ($this->otherObject->sky == self::COLOUR_BLUE) {
return true;
} else {
return false;
}
}
}
// Call doThings() statically to get its value
$response = new MyClass($otherObject)
if ($response->isSkyBlue() === false) {
// Your logic goes here
}
* Note that your constructor should always be called __construct() as using the class name for the constructor has been deprecated since PHP 5.
If you are using a constructor, it wont return anything...it is not a normal function

Can't fix some errors with OOP: relating to constructor calling function

I am really new to OOP, and I am getting some errors with my first implementation of the __constructor method. The two errors are:
Notice: Undefined variable: _test in...
Fatal error: Cannot access empty property in ...
Here is my code:
<?php
class Info
{
private static $_test;
public function __construct()
{
$this->setIt(); //call setIt so $_test can be set to true or false for use by other functions in the class.
}
public function setIt()
{
if ("test" == "something") //simplified logic for demo purposes
$this->$_test = TRUE;
else
$this->$_test = FALSE;
}
public function getIt()
{
if ($this->$_test) { //if test is true or false do stuff/other stuff
//do stuff
} else {
//do other stuff
}
}
}
$myObj = new Info(); //initialise the object
?>
<?php echo $myObj->getIt(); ?> //surrounded by html in my original code. Here I am getting some 'stuff' or 'other stuff' depending on what setIt() returned to $_test.
Sorry if that is a bit convoluted.
Your accessing your property with a $ at the beginning of it. When accessing object properties in an object scope, you dont need to use $. However, you've declared $_test as static, so you would set / get them using self::$_test
class Info
{
private static $_test;
public function __construct()
{
$this->setIt();
}
public function setIt()
{
if ("test" == "something"){
self::$test = TRUE;
} else {
self::$test = FALSE;
}
public function getIt()
{
if (self::$_test) {
//do stuff
} else {
//do other stuff
}
}
}
$myObj = new Info(); //initialise the object
echo $myObj->getIt();
replace
$this->$_test = TRUE;
with
$this->_test = TRUE;
every where in you code.
While using $this then $ is not used with property name
This thread can be useful.
You defined $_test as static, so you should access it as:
self::$_test
or
static::$_test
Still, getters and setters should be meaningful, and be named after the field they are wrapping [i.e. getTest(), setTest($value)], even if you are just providing an example case.
If you are new to OOP, you'll be going to some troubles with understanding the difference between instance and static properties and methods.
Let's pretend to have a Circle class, which holds center and radius:
class Circle
{
public static PI = 3.141592653589793;
private $x;
private $y;
private $radius;
public function getX(){ return $this -> x;}
public function setX($x){ $this -> x = $x;}
public function getY(){ return $this -> y;}
public function setY($y){ $this -> y = $y;}
public function getRadius(){ return $this -> radius;}
public function setRadius($radius){ $this -> radius = $radius;}
public function __construct($x, $y, $radius)
{
$this -> setX($x);
$this -> setY($y);
$this -> setRadius($radius);
}
public function getArea()
{
return $this -> radius * $this -> radius * self::PI;
}
public function getLength()
{
return 2 * self::PI * $this -> radius;
}
}
x, y and radius are different for each circle [instance of the class] you build: they are instance variables:
$firstCircle = new Circle(0,0,10);
$secondCircle = new Circle(5,5,2);
...
On the other hand, PI is static because it belongs to the class itself: for every circle it holds that the length/diameter ratio is 3.1415...
You'll find out that static properties and methods have wider use in OOP, but that's enough in order to have a first glance into it.

Categories