phpUnit - 模拟php扩展异常对象

时间:2010-05-14 01:44:34

标签: php unit-testing exception mocking phpunit

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

我想以这样的方式模拟这个异常对象:当测试代码生成异常时,它只会回显基本消息而不是给我整个HTML消息。

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

我想问题是,你会在哪里附加模拟对象?看起来你不能干扰'throw new',这就是调用object方法的地方....

或者,如果你能以某种方式使用现有的phpunit异常功能以你想要的方式改变异常行为,以一般的方式为你的所有代码......但这似乎是hacky和坏.... / p>

编辑:这里有一些代码可以让事情更清楚:

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{
 ...

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

3 个答案:

答案 0 :(得分: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

    }   

}

然后在使用extract方法时添加测试,直到您隔离异常。

<强> [编辑]

以下是一些严肃的程序遗留代码:

<?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());
}

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

上述测试将被视为覆盖测试。可能存在漏洞,但这就是它的作用。因此,当我发芽方法时,通过萌芽从测试中获得更多的代码覆盖,我可以确保我不会破坏输出。

答案 1 :(得分:0)

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

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

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

答案 2 :(得分:0)

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

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();