2014-09-12 146 views
4

我有一個類來處理錯誤,包括異常。如果發現異常,我會將異常作爲參數傳遞給我的異常/錯誤處理程序。PHPUnit模擬異常

try { 
    someTrowingFnc(); 
} catch (\Exception $e) { 
    this->error->exception($e); 
} 

現在我想單元測試這個錯誤處理程序並模擬異常。

我發現很難嘲笑異常,以便我可以控制異常消息,文件和行。

$exceptionMock = $this->getMock('Exception', array(
    'getFile', 
    'getLine', 
    'getMessage', 
    'getTrace' 
)); // Tried all mock arguments like disable callOriginalConstructor 

$exceptionMock->expects($this->any()) 
    ->method('getFile') 
    ->willReturn('/file/name'); 

$exceptionMock->expects($this->any()) 
    ->method('getLine') 
    ->willReturn('3069'); 

$exceptionMock->expects($this->any()) 
    ->method('getMessage') 
    ->willReturn('Error test'); 

代碼的下面總是結果返回NULL

$file = $exception->getFile(); 
$line = $exception->getLine(); 
$msg = $exception->getMessage(); 

有一個變通嘲笑異常或我只是做錯了什麼?

+1

是您的對象拋出異常稱爲? 否則,您可以生成該模擬,但如果沒有引發它,或者您不生成該條件,則該模擬不會發生。 是否可以顯示所有的代碼,或者至少是該代碼的代碼?, 自2011年以來,我一直沒有與phpunit一起工作,所以記住這一點,但我的頭頂,我記得你有一個裝飾器來捕獲一個預期的異常,但你的情況似乎有點不同,你正在產生一個模擬,但是(這是我的假設),你沒有產生拋出異常本身的條件,所以你的斷言會失敗。 – 2014-09-13 03:10:25

回答

5

返回錯誤詳細信息(如getFile()等)的Exception類方法被定義/聲明爲final方法。這是PHPUnit目前在保護,私有和最終模擬方法方面的一個限制。

Limitations 
Please note that final, private and static methods cannot be stubbed or mocked. They are ignored by PHPUnit's test double functionality and retain their original behavior. 

正如在這裏看到:https://phpunit.de/manual/current/en/test-doubles.html

+0

解決方法的任何想法? – 2015-07-29 09:17:43

+0

我以爲你可以創建一個實現異常類的虛擬類。在這個函數中,當調用時你會明確地拋出一個錯誤,這樣你就可以知道確切的文件,行號等。使用測試用例調用函數並捕獲拋出的顯式異常,聲明文件,行號等正確。 – antoniovassell 2015-08-01 00:33:29

0

這是一個黑客攻擊的一位,但嘗試添加像這樣到你的TestCase:

/** 
* @param object $object  The object to update 
* @param string $attributeName The attribute to change 
* @param mixed $value   The value to change it to 
*/ 
protected function setObjectAttribute($object, $attributeName, $value) 
{ 
    $reflection = new \ReflectionObject($object); 
    $property = $reflection->getProperty($attributeName); 
    $property->setAccessible(true); 
    $property->setValue($object, $value); 
} 

現在你可以改變這些值。

$exception = $this->getMock('Exception'); 
$this->setObjectAttribute($exception, 'file', '/file/name'); 
$this->setObjectAttribute($exception, 'line', 3069); 
$this->setObjectAttribute($exception, 'message', 'Error test'); 

當然,你還沒有真正嘲笑類,雖然這仍可能是有用的,如果你有一個更復雜的自定義異常。此外,您將無法計算該方法被調用的次數,但由於您使用的是$this->any(),因此我認爲這並不重要。

它也是有用的,當你測試一個異常是如何處理的,例如是否有其他方法(如記錄器)與異常消息作爲參數