如何在进行单元测试时覆盖php://输入

joh*_*yan 19 php phpunit unit-testing zend-framework

我正在尝试使用Zend和PHPUnit为控制器编写单元测试

在代码中我从php:// input获取数据

$req = new Zend_Controller_Request_Http();
$data = $req->getRawBody();
Run Code Online (Sandbox Code Playgroud)

当我测试真实的应用程序时,我的代码工作正常,但除非我可以提供数据作为原始http帖子,否则$ data将始终为空.getRawBody()方法基本上调用file_get_contents('php:// input'),但是如何覆盖它以便将测试数据提供给我的应用程序.

Mit*_*aro 10

我遇到了同样的问题,我修复它的方法是将'php://input'字符串作为可在运行时设置的变量.我知道这并不直接适用于这个问题,因为它需要修改Zend Framework.但同样的,它可能对某人有所帮助.

例如:

<?php
class Foo {

    public function read() {
        return file_get_contents('php://input');
    } 
}
Run Code Online (Sandbox Code Playgroud)

会成为

<?php
class Foo {

    public $_fileIn = 'php://input';

    public function read() {
        return file_get_contents($this->_fileIn);
    }

}
Run Code Online (Sandbox Code Playgroud)

然后在我的单元测试中我可以做到:

<?php
$obj = new Foo();
$obj->_fileIn = 'my_input_data.dat';
assertTrue('foo=bar', $obj->read());
Run Code Online (Sandbox Code Playgroud)

  • 您还可以拥有受保护的属性,并使用测试中的反射将其更改为public.所以对于生产来说,你的代码更清洁一些.(假设php 5.3) (2认同)

Mic*_*ing 7

您可以尝试在单元测试中模拟对象.像这样的东西:

$req = $this->getMock('Zend_Controller_Request_Http', array('getRawBody'));
$req->method('getRawBody')
    ->will($this->returnValue('raw_post_data_to_return'));
Run Code Online (Sandbox Code Playgroud)


Luk*_*son 2

前提是,正如你所说,与...$req->getRawBody()相同file_get_contents('php://input')

$test = true; /* Set to TRUE when using Unit Tests */

$req = new Zend_Controller_Request_Http();
if( $test )
  $data = file_get_contents( 'testfile.txt' );
else
  $data = $req->getRawBody();
Run Code Online (Sandbox Code Playgroud)

这不是一个完美的解决方案,但类似于我过去在设计处理管道电子邮件的脚本时所使用的方法,取得了巨大的成功。