开发者

phpUnit - mock php extended exception object

I'm testing some legacy code that extends the default php exception object. This code prints out a custom HTML error message.

I would like to mock this exception object in such a way that when the tested code generates an exception it will just echo the basic message instead of giving me the whole HTML message.

I cannot figure out a way to do this. It seems like you can test for explicit exceptions, but you can't change in a general way the behavior of an exception, and you also can't mock up an object that extends a default php functionality. ( can't think of another example of this beyond exceptions... but it would seem to be the case )

I guess the problem is, where would you attach the mocked object?? It seems like you can't interfere with 'throw new' and this is the place that the object method is called....

Or if you could somehow use the existing phpunit exception开发者_StackOverflow社区 functionality to change the exception behavior the way you want, in a general way for all your code... but this seems like it would be hacky and bad....

EDIT: here is some code to make things clearer:

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

so, my question, is there a way to deal with this overriden class, without doing it on a case by case basis? what if I'm not testing the behavior of the exception, just the code that causes the exception?


I would first write a test that captures the exception generation behavior:

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.');
}

Now you can do several things with this coverage test. You can either fix up the exception, or fix the code that causes the exception.

Another thing you can do is wrap the entire file.php in a class:

 class FooClass {

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

    }   

}

Then add tests while using extract method until you isolate exception.

[EDIT]

Here is some serious procedural legacy code:

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

function countNewMessages($user_id) {
}

function countNewOrders() {
}

function countNewReturns() {
}

function getDB($init = NULL) {
}

function getDisplay() {
}

getDisplay();

?>

And here is the wrapped class:

<?php
require_once '';  //helper file

class Displayer {
    function countNewMessages($user_id) {
    }

    function countNewOrders() {
    }

    function countNewReturns() {
    }

    function getDB($init = NULL) {
    }

    function getDisplay() {
    }
}
?>

And now I can test it:

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

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

And test the individual functions in it. And if I can further sprout methods on it.

The above test would be considered a coverage test. There may be bugs in it, but that is what it does. So as I sprout methods the get more code coverage from tests by sprouting that I can make sure I don't break the output.


The extened PHP exception object "prints" a costum HTML error page? You mean its error message is an entire HTML page? That's not very clever...

What you can do about it is to replace the default exception handler (see this function), call getMessage on the exception and parse the HTML error page to extract the message. Then you can print the error message and kill the script. Like this (in PHP 5.3):

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


OK, I misunderstood the question. If the script you're testing catches the error and then echoes an error page, then this has nothing to do with exceptions. You can use the 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();
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜