2014-01-13 186 views
2

我正在编写一个MVC框架,该框架利用一个库来帮助管理输入变量(例如get,post等)。模拟单元测试的HTTP请求

现在,我测试了POST并迫使它们的值到$ _ POST和$ _GET超全局,分别GET变量,但我对测试时PUT和DELETE请求变量达到一个路障。

实施例:

public function testGET() 
{ 
    $_GET['test'] = 'test value'; 

    $get_value = Input::get('test', '[default value]'); 

    assertEquals('test value', $get_value); 
} 

是否有嘲笑/模拟这些变量或使用各种可用的方法,以模拟一个HTTP请求(具体而言,GET,POST,PUT,DELETE)的好方法?

+2

你会模拟Input :: get()返回你期望的文本,然后测试你的代码的行为。这听起来像是你在正确的轨道上,你只需要做Mock而不是格式化全局变量。 –

回答

3

我有时觉得人们过度使用Design for Testability,最后得到的结果是80%的复杂度似乎只是为了使测试更容易。我觉得切换到对单元测试变得混乱的东西的功能测试通常会更好。

但是对于我给出的PHP超级全局变量。所以我尽量避免在任何框架代码中使用$ _POST或$ _GET,而是使用参数,或者如果代码太丑陋,那么类成员或静态成员。

所以,你的get()函数可以改写这样的:

public static function get($name,$default,$GET=null) 
{ 
    if($GET===null)$GET=$_GET; //For non-test code 
    if(!array_key_exists($name,$GET))return $default; 
    return $GET[$name]; 
} 

那么你的测试变为:

public function testGET() 
{ 
    $GET=array('test' => 'test value'); 
    $get_value = Input::get('test', '[default value]', $GET); 
    $this->assertEquals('test value', $get_value); 
} 

这很快得到尴尬的时候调用到输入::得到()深藏在呼叫层次结构中;那么静态类成员就更好了。要使用类成员,$ GET可以通过init()函数传递。但是,如果有一个init()功能是不合适的,这是可以做到这样的:

public static $GET=null; 

public static function get($name,$default) 
{ 
    if(self::$GET===null)self::$GET=$_GET; //Init on first call 
    if(!array_key_exists($name,self::$GET))return $default; 
    return $GET[$name]; 
} 

然后测试变为:

public function testGET() 
{ 
    Input::$GET=array('test' => 'test value'); 
    $get_value = Input::get('test', '[default value]'); 
    $this->assertEquals('test value', $get_value); 
} 

旁白:其他(非测试)的原因,我喜欢这种方法是它允许客户端代码来选择使用$_GET$_POST$_REQUEST等,所以我会说出静态变量self::$INPUT,并有一个init()功能在用户有望在$_POST$_GET或任何他们想传递。

问题的后半部分询问有关测试PUT和DELETE数据的问题。但是你没有说它是如何在真正的代码中被处理的。你有类似于这样的回答显示出一些代码:https://stackoverflow.com/a/5374881/841830

如果是这样,一个办法是嘲笑getContent()功能,还有显示,返回而不是从php://input得到它硬编码的文本。另一种方法是在另一个函数(在你的真实类中),主要用于测试,在第一次使用该变量的调用之前进入并设置$this->content。 ($this->content在这个答案基本上就像我前面提到的变量self::$INPUT)。

-3

请求标头是PHP超级全局$ _SERVER的一部分。您可以在$ _SERVER中设置适当的标题。例如:

<?php 
    $_SERVER['REQUEST_METHOD'] = 'PUT'; 
    // Now you should be able to pull data 
?> 

查看PHP $ _SERVER手册。 http://php.net/manual/en/reserved.variables.server.php