在phpunit test

时间:2015-05-08 12:23:34

标签: php unit-testing phpunit http-post global

使用PHPUnit测试我的控制器时遇到一些问题。

到目前为止我正在编写的代码是实现$_POST或其他请求变量:

$_SERVER['REQUEST_METHOD'] = 'POST';
$_POST = array(
    'test' => true
);

大多数测试都是这样完美的,直到我遇到使用filter_input_array函数的方法:

$_SERVER['REQUEST_METHOD'] = 'POST';
$_REQUEST = $_POST = $GLOBALS['_POST'] = array(
    'test' => true
);

// ....

var_dump(filter_input_array(INPUT_POST));
  

NULL

我不愿意从我的代码中移除filter_input函数,但我无法让它们在测试中工作。

  

Versionings:
  PHP 5.5.9-1ubuntu4.9(cli)(建于2015年4月17日11:44:57)
  Apache / 2.4.7(Ubuntu)
  Sebastian Bergmann和贡献者的PHPUnit 4.6.6。

任何帮助将不胜感激。

编辑2015.05.11

使用$_SERVERCONTENT_LENGTH设置CONTENT_TYPE并不能解决问题。我的PHP版本不允许我按照PHP 5.6.0 chagelog中描述的方式写入php://stdin(或者我理解它),但file_put_contents(STDIN,..)成功但无论如何都不起作用。

因为它是一个phpunit测试,可能有某种注释或phpunit.xml条目我还不知道,这可能会以php-cgi POST setting的方式解决这个问题。

4 个答案:

答案 0 :(得分:9)

如果filter_input_array的输入只能由初始请求设置,而不是在运行时更改,那么仍然测试它的唯一方法是通过制作另一个测试脚本的基本测试代理具有正确POST数据并处理响应的HTTP请求。

main_test.php:

<?php
$data = array(
    'testname' => 'yourtestname',
    'some_post_var' => 'some_value'
);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://localhost/proxy_test.php");
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);

curl_close($ch);

if ($response == 'pass') {
  // test passed
}

proxy_test.php

<?php
$test_name $_POST['testname']; // what test to run?
$response = run_test($test_name); // run test that uses filter_input_array
if ($response) {
    echo "pass"; // used by main_test.php to check if test passed
} else {
   echo "fail";
}

答案 1 :(得分:5)

似乎这是PHP的限制,filter_input_array()不允许在运行时修改$_POST数组。有关更多信息,请参阅this bug。解决方法可能是使用the other filter functions之一并自己传递$_POST数组。

答案 2 :(得分:1)

如果未设置任何参数,则此函数返回NULLnot an array of NULL values.

//请求中没有设置POST变量

$_POST = array();
$args = array('some_post_var' => FILTER_VALIDATE_INT);
$myinputs = filter_input_array(INPUT_POST, $args);
var_dump($myinputs);

Expected Output: array(1) { ["some_post_var"]=> NULL } 
  

实际输出:NULL

在过滤输入数组时,请注意除FILTER_REQUIRE_ARRAY之外设置的标记。例如,设置标志如下:

 <?php 
    $filter = array( 
    'myInputArr' => array('filter' => FILTER_SANITIZE_STRING, 
                          'flags' => array('FILTER_FLAG_STRIP_LOW', 'FILTER_REQUIRE_ARRAY')) 
    ); 

$form_inputs = filter_input_array(INPUT_POST, $filter); 
?> 
  

..无论如何都会导致空格$ form_inputs ['myInputArr']   $ _POST ['myInputArr']包含什么。

答案 3 :(得分:0)

一种解决方法是使用辅助方法在您的filter_input_array内部运行,然后在测试期间模拟此方法以使用其他类似filter_var_array的方法。

例如,此用例可以通过执行以下操作来完成:

class Data_Class {

    protected function i_use_filters() {
        return $this->filter_input_array();
    }


    protected function filter_input_array() {
        return filter_input_array( INPUT_POST );
    }
}

class Test_Class extends TestCase {

    public function test_filters() : void {
        $mock = $this->getMockBuilder( Data_Class::class )
                     ->setMethods( [ 'filter_input_array' ] )
                     ->getMock();
        $mock->method( 'filter_input_array' )
             ->willReturnCallback( function () {
                 if ( ! isset( $_POST ) ) {
                     return null;
                 }
                 return \filter_var_array( $_POST );
             } );

        $_POST['test'] = true;
        $this->assertTrue( $mock->i_use_filters()['test'] );
    }
}