PHPUnit testing method that contains function that needs to be mocked - php

Hello im testing a method which uses this function, that is not in any class. It needs to be as it is without the class because this is in wordpress. I need to mock this function, i declared it twice once it will return true and second time it will return false, but it gave me an error with redeclaration. What should i do to mock this method twice?
function wcs_order_contains_subscription() {
return false;
}
//testing stuff
function wcs_order_contains_subscription() {
return true;
}
//test another stuff
EDIT:
for ($i = 0; $i < 2; $i++) {
if ($i == 0) {
function wcs_order_contains_subscription() {
return false;
}
var_dump($gateway->process_payment($order_id));
} else {
function wcs_order_contains_subscription() {
return true;
}
var_dump($gateway->process_payment($order_id));
exit();
}
}

Related

How to exit from a specific function in PHP?

I have multiple nested methods inside a PHP class. What I want to do is, based on certain circumstances, I want to exit from NOT JUST the current method, but 2 above it, then the leftover code should continue running. Now the issue with die(), exit() is that they end the full script and I don't want that. I simply want to go a few methods up and continue the script.
Of course, there's the old school method of returning a value in each method and check if it's false for example. But that way I'll have to write tons of additional code if I have like 50 nested methods. Here's what I have right now - it's a very basic usage here, I'm using it in a lot more complicated scenarios (using PHP 7.2.4):
class Sites
{
public function __construct()
{
$this->fn1();
}
public function fn1()
{
$fn2 = $this->fn2();
echo 'I want this to be displayed no matter what!';
}
public function fn2()
{
$fn3 = $this->fn3();
if ($fn3)
{
return true;
}
}
public function fn3()
{
$fn4 = $this->fn4();
if ($fn4)
{
return true;
}
}
public function fn4()
{
$random = rand(1, 100);
if ($random > 50)
{
return true;
}
else
{
// I want to exit/break the scirpt to continue running after
// the $fn2 = $this->fn2() call in the $this->fn1() function.
exit();
echo "This shouldn't be displayed.";
}
}
}
Just as mentioned in the code comments, I want to break the script - if the random number is below 50 and go back to fn1() but continue executing the echo function there.
Is this possible somehow? Please let me know if you need more information and I'll provide.
You can use Exceptions to do this, not particularly elegant, but this should do what your after, replace these methods...
public function fn1()
{
try {
$fn2 = $this->fn2();
}
catch ( Exception $e ) {
}
echo 'I want this to be displayed no matter what!';
}
public function fn4()
{
$random = rand(1, 100);
if ($random > 50)
{
return true;
}
else
{
// I want to exit/break the scirpt to continue running after
// the $fn2 = $this->fn2() call in the $this->fn1() function.
//exit();
throw new Exception();
echo "This shouldn't be displayed.";
}
}
How about regular function call with a flag?
class Sites
{
protected $flag = false;
public function __construct()
{
$this->fn1();
}
public function fn1()
{
if ($this->flag) {
$this->flag = true;
} else {
echo 'I want this to be displayed no matter what!';
$fn2 = $this->fn2();
}
}
public function fn2()
{
$fn3 = $this->fn3();
if ($fn3)
{
return true;
}
}
public function fn3()
{
$fn4 = $this->fn4();
if ($fn4)
{
return true;
}
}
public function fn4()
{
$random = rand(1, 100);
if ($random > 50)
{
return true;
}
else
{
// I want to exit/break the scirpt to continue running after
// the $fn2 = $this->fn2() call in the $this->fn1() function.
//exit();
$this->flag = true;
$this->fn1();
exit();
echo "This shouldn't be displayed.";
}
}
}
$sites = new Sites;
I hope this helps!

Better way to check for empty function args

Pretty much all my class methods start the same way, by checking to see if the arguments passed are empty or not (variations for where I am expecting bools and int-0's)
Is there a less repetitive way of checking the values?
public function updateproduct($product, $storeid) {
if ( empty($product) || empty($storeid) ) {
return false;
}
// do stuff
}
Using func_num_args to iterate over an array of arg values returned by func_get_args is one way to accomplish what you are after
function foo($numargs, $arg_list) {
for ($i = 0; $i < $numargs; $i++) {
if (empty($arg_list[i])) {
return false;
}
}
return true;
}
function bar($arg1, $arg2) {
if (!foo(func_num_args(), func_get_args())) {
//...
}
}
bar('baz', null);
This function tests to see if any of the arguments passed to it are empty. The upside is the simplicity. The downside is that it does not short-circuit if an empty value is found.
I imagine if you were to notice the impact of it not short-circuiting, you are sending too many params to your function.
function anyEmpty(...$args){
return array_filter($args) !== $args;
}
Then our usage in updateProduct function:
function updateProduct($product, $storeId){
if (anyEmpty($product, $storeId)) {
return False;
}
//do your stuff
return True;
}
Or alternatively, if you would prefer to specify the params dynamically:
if (anyEmpty(...func_get_args())) {
return False;
}

When should I return?

I am struggling to create an access object to sections stored in the Database. This is a skellington of the process, this contains static data until I can get the principle working.
class User {
const IS_ADMIN = 1;
const IS_MODERATOR = 2;
const IS_MEMBER = 4;
}
This class will auto-load data from the database eventually but for the time being, this class has default values.
class Scope {
private $priv = [];
public function __construct() {
$this->priv = [1];
}
public function getPrivilidges() {
return $this->priv;
}
}
This is where it messes up, I can tell that the second and third conditions cannot be met if the first fails, how can I stop this?
class Priverlidges {
public function canView($type, Scope $scope) {
if($type & User::IS_ADMIN) {
foreach($scope->getPrivilidges() as $p) {
if($p == User::IS_ADMIN) continue;
return false;
}
return true;
}
if($type & User::IS_MODERATOR) {
foreach($scope->getPrivilidges() as $p) {
if($p == User::IS_MODERATOR) continue;
return false;
}
return true;
}
if($type & User::IS_MEMBER) {
foreach($scope->getPrivilidges() as $p) {
if($p == User::IS_MEMBER) continue;
return false;
}
return true;
}
}
}
Example usage which works fine when the default value of the priverlidge is 1:
echo (int)(new Priverlidges)->canView(User::IS_ADMIN, new Scope());
Example usage which works fine when the default value of the priverlidge is 2:
echo (int)(new Priverlidges)->canView(User::IS_MODERATOR | User::IS_ADMIN, new Scope()); // it returns false at the first condition
Can anyone help me with when to return true or false? Thanks in advance.
P.S - Users can be both Mods and Admins
EDIT: I have tried to use in_array() and still am unsure when to return the value true or false because it get's overwrite if the second method runs.
I figured it out. First, check the user is not already authenticated using a placeholder ($this->_state). Then check the type of user and check it is inside the scope.
class Priverlidges {
private $_state = false;
public function canView($type, Scope $scope) {
if(!$this->_state && $type & User::IS_ADMIN && in_array(User::IS_ADMIN, $scope->getPrivilidges())) {
$this->_state = true;
}
if(!$this->_state && $type & User::IS_MODERATOR && in_array(User::IS_MODERATOR, $scope->getPrivilidges())) {
$this->_state = true;
}
if(!$this->_state && $type & User::IS_MEMBER && in_array($scope->getPrivilidges(), User::IS_MEMBER)) {
$this->_state = true;
}
return $this->_state;
}
}

How to pass custom error messages from Model to Controller Laravel

Ok so I currently have this Controller which basically retrieves a Model and does some calculation.
Original code has tonnes of calculation but this is a trimmed down version for simplicity.
I wanted to move all logic to the Model and have built the code below it so far but can not figure out how to pass the custom messages to the Controller.
I am a beginner in Laravel so trying to achieve this in an easy to understand way so I can maintain it and managed to get the code below working but without custom error messages being passed onto the Controller.
Can you give me an example code of how you are passing custom error messages to controller
This is the original code in controller.
Controller
public function getDetail()
{
$request = Model::where('id','=',8)->first();
if($request)
{
if($request->number >= 5)
{
return Redirect::back()->withMessage('You have 5 or more');
}
if($request->number > 0 && $request->number < 5)
{
return Redirect::back()->withMessage('You have between 1 and 4');
}
if($request->number <= 0)
{
return Redirect::back()->withErrors('You do not have enough points');
}
}
else
{
return Redirect::back()->withErrors('No details found');
}
}
This is the new code I tried to build to move logic to model but could not figure out how to pass the custom error messages along?
Model
Class Profile
{
private $model
function __construct()
{
$this->model = Model::where('id','=',8)->first();
}
public function Notification()
{
if($this->model->number >=5)
{
return true;
}
if($this->model->number > 0 && $this->model->number < 5)
{
return true;
}
if($this->model->number <=0)
{
return false;
}
}
}
Controller
public function getDetail()
{
$request = new Profile;
$result = $request->Notification();
if($result)
{
return Redirect::back()->withMessage(????????);
}
else
{
return Redirect::back()->withErrors(????????);
}
}
Just return the message from the Model function and use it in the controller to return like shown below.
Model function
public function Notification()
{
$returnArray = array();
if($this->model->number >=5)
{
$returnArray['isMessage'] = true;
$returnArray['message'] = "You have 5 or more";
}
if($this->model->number > 0 && $this->model->number < 5)
{
$returnArray['isMessage'] = true;
$returnArray['message'] = "You have between 1 and 4";
}
if($this->model->number <=0)
{
$returnArray['isError'] = true;
$returnArray['error'] = "You do not have enough points";
}
return $returnArray;
}
Controller function
public function getDetail()
{
$request = new Profile;
$result = $request->Notification();
if(isset($result['isMessage']) && $result['isMessage'] == true)
{
return Redirect::back()->withMessage($result['message']);
}
else if (isset($result['isError']) && $result['isError'] == true)
{
return Redirect::back()->withErrors($result['error']);
}
}
Ideally speaking you should not create an object of Model in controller. You can just create the function as a static method inside model and call it from controller.

Preserving variable values within a PHP function

I have a function which I call multiple times within a script. The value returned from the function will always be the same. I would rather not execute all the script within the function each time since the returned value is always the same. I am not using OOP so can't assign it to a object property and do the script in the constructor.
Below is my attempt. It doesn't work since $status is not set until it later is defined as a static variable. How can I accomplish my goal?
function checkStatus()
{
if(!isset($status))
{
//Do some script to determine $cond
if($cond) {static $status=0;}
else {static $status=1;}
}
return $status;
}
This should do what you need:
function checkStatus()
{
static $status;
if(!isset($status))
{
if (TRUE) // Whatever your truth condition will be
{
$status = 1;
}
else
{
$status = 0;
}
}
return $status;
}
You could pass the variable by reference: http://www.php.net/manual/en/language.references.pass.php
function checkStatus(&$status)
{
//Do some script to determine $cond
if($status == 0) {
$status=1;
}
else {
$status=0;
}
}
$status = 0;
checkStatus($status);
echo $status; //this should display 1;

Categories