2010-05-14 83 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