2010-05-14 114 views
2

我正在测试一些扩展了默认php异常对象的遗留代码。此代码打印出一个自定义HTML错误消息。phpUnit - 模拟php扩展异常对象

我想嘲笑这个异常对象的方式,当被测试的代码生成一个异常时,它只会回应基本消息,而不是给我整个HTML消息。

我想不出有办法做到这一点。您似乎可以测试显式异常,但不能以通常方式更改异常的行为,并且也不能模拟扩展默认php功能的对象。 (不能认为这超出了例外另一个例子......但它似乎是这种情况),我想这个问题是

,在那里你会并附上模拟的对象?似乎你不能干预'抛新',这是对象方法被称为的地方....

或者,如果你能以某种方式使用现有的phpunit异常功能来改变异常行为的方式你想,在所有代码的一般方式...但是这似乎将是哈克和坏....

编辑:这里是一些代码,以使事情更清晰:

class FooTest extends PHPUnit_Framework_TestCase{ 

    public function testBar(){ 
     include '/path/to/file.php'; //generates exception 

     $this->assertTrue($baz);    
    } 
} 
... 
//overridden exception class 
class Foo_Exception extends ErrorException{ 
... 

所以,我的问题是,有没有办法处理这个被覆盖的类,而不是根据具体情况来做呢?如果我不测试异常的行为,只是导致异常的代码?

+0

好了,现在我感到困惑。要么包括的例外没有被捕获,然后我的第一个答案成立或被捕获,我的第二个答案成立。这种例外是无关紧要的。 – Artefacto 2010-05-14 23:46:22

+0

你是对的...我很困惑ob_start如何处理... 但是...你的解决方案确实能够抑制错误消息,但它也意味着它将所有输出同等对待...... I猜测我是在问一个更具体的解决方案来处理异常类本身......但现在我认为这一切似乎并不可行......或者一定需要...... I猜测处理对象行为的最佳情况是引发每个案例的例外情况。 有时事情只有当你问一个模糊的问题时才有意义...... – awongh 2010-05-15 01:02:59

回答

1

我会先写捕获异常生成行为测试:

include '/path/to/file.php'; //generates exception 
public function testCatchFooException() { 
    try { 
     $this->assertTrue($baz);    
    } 
    catch (Exception $expected) { 
     $this->assertEquals('This is expected html from exception', $expected->getMessage()); 
     return; 
    } 

    $this->fail('An expected Exception has not been raised Foo_Excpetion.'); 
} 

现在你可以做几件事情与此覆盖测试。您可以修复异常,或修复导致异常的代码。

你可以做的另一件事是一类包住整个file.php

class FooClass { 

    function runFoo() { 
     include '/path/to/file.php'; //generates exception 

    } 

} 

然后同时采用萃取法,直到您隔离异常增加的测试。

[编辑]

下面是一些严重的程序遗留代码:

<?php 
require_once 'helper.php'; //helper file 

function countNewMessages($user_id) { 
} 

function countNewOrders() { 
} 

function countNewReturns() { 
} 

function getDB($init = NULL) { 
} 

function getDisplay() { 
} 

getDisplay(); 

?> 

这里是包装类:

<?php 
require_once ''; //helper file 

class Displayer { 
    function countNewMessages($user_id) { 
    } 

    function countNewOrders() { 
    } 

    function countNewReturns() { 
    } 

    function getDB($init = NULL) { 
    } 

    function getDisplay() { 
    } 
} 
?> 

现在我可以测试它:

function testGetDisplay() { 
    $display = new Displayer(); 

    $this->assertEquals('html code', $display->getDisplay()); 
} 

并测试其中的各个功能。如果我可以进一步发芽的方法就可以了。

上述测试将被视为覆盖测试。它可能存在错误,但它就是这样。所以,当我发芽的方法,通过发芽获得更多的测试代码覆盖率,我可以确保我不会打破输出。

+0

你能解释更多关于你的第二个例子吗?测试会是什么样子?你会做$ foo_instance = new FooClass ...然后捕获... $ foo_instance-> runFoo()...在测试中? – awongh 2010-05-15 01:32:13

+0

这是我从Michael Feather的书WEWLC得到的。任何方式都是一个对象。看我的编辑。 – Gutzofter 2010-05-15 02:13:57

0

扩展后的PHP异常对象“打印”了一个错误的HTML错误页面?你的意思是它的错误信息是一个完整的HTML页面?这不是很聪明...

你可以做的是替换默认的异常处理程序(请参阅this function),在异常时调用getMessage并解析HTML错误页面以提取消息。然后您可以打印错误消息并杀死脚本。像这样(在PHP 5.3中):

set_exception_handler(
    function (Exception $e) { 
     die(parse_html_error_page($e->getMessage())); 
    } 
); 
+0

好吧,脚本在包含一个HTML文件以输出给用户之前,通过一些较小的方式处理错误,并带有'漂亮'格式的消息。我同意这可能不是最模块化的方法...... 但我不认为这会起作用,因为这个错误处理类正在处理脚本中捕获到的错误消息。 set_error_handler只适用于未被捕获的错误.... – awongh 2010-05-14 02:09:21

0

好的,我误解了这个问题。如果您正在测试的脚本捕获错误,然后回显错误页面,那么这与异常无关。您可以使用ob_家庭:

ob_start(); 
include $file; 
$contents = ob_get_contents(); 

if (result_is_error($contents)) 
    die(extract_error_from_result($contents)); 
else 
    echo $contents; 

ob_end_clean(); 
+0

我应该包含一些代码或伪代码以使其更清楚,但我认为这也不会起作用:此线程表示您仍然会看到抛出即使你缓冲输出的异常.... http://stackoverflow.com/questions/2201841/how-do-i-stop-php-output-buffering-from-eating-error-messages 当我鸽子进一步进入代码,它也看起来像错误是源于更多的地方比我原本以为.... 我想也许我只是写了一个定义不清的问题.... – awongh 2010-05-14 23:32:56

+0

你可能会看到抛出异常,如果他们没有被捕获,并且异常处理程序吐出一条错误消息并杀死脚本。我不确定这是否是默认异常处理程序的行为,但即使是这样,它在捕获异常时也不适用。 – Artefacto 2010-05-14 23:47:32