我有时觉得人们过度使用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
)。
你会模拟Input :: get()返回你期望的文本,然后测试你的代码的行为。这听起来像是你在正确的轨道上,你只需要做Mock而不是格式化全局变量。 –