2010-07-11 62 views
17

我试图写一个使用Zend和PHPUnit的我怎么重写PHP:做单元测试时//输入

在代码中,我从PHP获取数据的控制器单元测试://输入

$req = new Zend_Controller_Request_Http(); 
$data = $req->getRawBody(); 

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

回答

3

倘若$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(); 

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

+0

叶氏,不是一个完美的解决方案,但如何我已经决定要实现这一点。谢谢。 – 2010-07-12 21:45:24

+0

我不会推荐这个解决方案 - 使用if语句在单元测试和生产中执行不同的代码。理想情况下,您希望代码在两个世界中执行相同的逻辑语句。请参阅下面的@ MitMaro解决方案,该解决方案使用可配置的输入路径。 – 2016-11-10 23:04:16

7

你可以尝试在单元测试中嘲笑对象。事情是这样的:

$req = $this->getMock('Zend_Controller_Request_Http', array('getRawBody')); 
$req->method('getRawBody') 
    ->will($this->returnValue('raw_post_data_to_return')); 
+0

所以这将工作,如果我传递Zend_Controller_Request_Http对象到我正在测试的代码中,不幸的是控制器在引擎盖下处理所有这些。所以我认为唯一的方法就是改变我的应用程序来测试我所处的环境并处理特殊情况。 – 2010-07-12 21:44:38

10

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

例如:

<?php 
class Foo { 

    public function read() { 
     return file_get_contents('php://input'); 
    } 
} 

将成为

<?php 
class Foo { 

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

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

} 

然后在我的单元测试,我可以这样做:

<?php 
$obj = new Foo(); 
$obj->_fileIn = 'my_input_data.dat'; 
assertTrue('foo=bar', $obj->read()); 
+2

你也可以有一个受保护的属性,并使用测试中的反射将其更改为公共。所以对于生产你的代码是一个更清洁。 (假设php 5.3) – edorian 2011-04-23 04:02:32

0

Zend_Controller_Request_HttpTestCase包含设置和获取各种HTTP请求/方法响应。

例如: $req = new Zend_Controller_Request_HttpTestCase; $req->setCookie('cookie', 'TRUE'); $test = $this->controller->cookieAction($req); $this->assertSame($test, TRUE);