How to make a PHPUnit test that depends on ~ real ~ POST / GET data?

I created a PHP class that converts filter_input functions to simplify our developer life.
To test the HTML form with the url , name and age fields, the code would be:

 $post = Filter::POST(); if ($post->validate_string('name') && $post->validate_integer('age')) { $url = $post->sanitize_url('url'); } 

It will be the same as:

 if (filter_input(INPUT_POST,'name',FILTER_UNSAFE_RAW) && filter_input(INPUT_POST,'age',FILTER_VALIDATE_INTEGER)) { $url = filter_input(INPUT_POST,'url',FILTER_SANITIZE_URL); } 

Well, I think the code is done, and now I would like to create a PHPUnit test for it.

The problem is that I have no idea how to fake GET / POST data using the PHPUnit method, and not for this case.
I do not need to insert values ​​into $_POST , I need "real" data on it, because filter_input works with the received script data, and not with the actual $_POST superglobal.

I tried using the following PHPT test and the PHPUnit method to achieve this, without any success:

 --TEST-- Generates POST and GET data to be used in FilterTest.php --POST-- name=Igor&age=20 --GET-- name=Igor&age=19 --FILE-- <?php echo $_POST['nome'].' = '.$_POST['idade']; ?> --EXPECT-- Igor = 20 

 public function testPhpt() { $phpt = new PHPUnit_Extensions_PhptTestCase('FilterTest_data.phpt', array('cgi' => 'php-cgi')); $result = $phpt->run(); $this->assertTrue($result->wasSuccessful()); } 

EDIT

Source Code : http://pastebin.com/fpw2fpxM
Code used for initial testing : http://pastebin.com/vzxsBQWm
(sorry for the Portuguese language, I know that it would be better to code in English, but this is how everything works here, where I work. If you really think that it is really necessary, I can translate the code).

Any idea on what I can do to test this class?

+7
php testing phpunit
source share
2 answers

You cannot fake raw POST data. But the problem lies in your code: it cannot be checked per unit. Instead:

 if (filter_input(INPUT_POST,'name',FILTER_UNSAFE_RAW) && filter_input(INPUT_POST,'age', FILTER_VALIDATE_INTEGER)) { $url = filter_input(INPUT_POST,'url',FILTER_SANITIZE_URL); } 

If you have:

 if (filter_var($data['name'], FILTER_UNSAFE_RAW) && filter_var($data['age'], FILTER_VALIDATE_INT)) { $url = filter_var($data['url'], FILTER_SANITIZE_URL); } // where $data is a copy of $_POST in that case 

Would provide your block of code with testability and equal to your previous code.

PS: FILTER_VALIDATE_INTEGER is not valid. The correct constant for this is FILTER_VALIDATE_INT

+2
source share

You have 2 problems with your code. First, you get access to global variables that are difficult to verify. Secondly, you strongly bind the class to specific data (post, get, etc.).

What you need to do is make the class this interface:

 $filter = new Filter($_POST); $filter->validate_string('name'); 

The benefits should be obvious. You do not need to use $_POST or $_GET or any other predefined type as input. You can not only check the input from any source (since you just pass it to the constructor), more importantly, you can enter any data where you like testing.

Inputs, I skipped the part about using filter_input . The solution is to use filter_var . It allows you to run filters on any variable.

+2
source share

All Articles