2014-12-27 230 views
0

我遇到了TDD和不可能例外的問題。不可能例外的TDD

比方說,我們有一個名爲Foo(例如)類:

Class Foo { 
    public String getString(boolean shouldThrow) throws Exception { 
     if(shouldThrow) throw new Exception(); 
     return "nonsense"; 
    } 
} 

美孚僅在某些情況下拋出一個異常(爲簡單起見我把這裏的布爾)。

現在我想創建一個名爲Bar的類,它可以在不引發異常的情況下反轉Foo的字符串。

測試:

class BarTest { 
    public void testShouldReturnReversedStringOfBar() { 
     Bar bar = new Bar(); 
     assertEquals("esnesnon", bar.getReversedString()); 
    } 
} 

我知道,布爾是假所有的時間。所以方法getReversedString()永遠不會拋出異常。但是因爲它不會引發異常,所以我不能寫一個斷言,這導致我在Bar內寫入try/catch塊。

所以測試將是這樣的:

class BarTest { 
    public void testShouldReturnReversedStringOfBar() { 
     Bar bar = new Bar(); 
     try { 
      assertEquals("esnesnon", bar.getReversedString()); 
     } catch (Exception e) { 
      // ... will never happen 
     } 
    } 
} 

但是,這是不好的,因爲異常不會發生,我必須每次使用getReversedString(時間寫的try/catch塊)方法。 所以我想這個類是這樣的:

class Bar { 
    public String getReversedString() { 
     Foo foo = new Foo(); 
     try { 
      String s = foo.getString(false); 
     } catch (Exception e) { 
      // will never happen... 
     } 
     // ... reverse string ... 
     return reversedString; 
    } 
} 

但由於異常將永遠不會發生,我不能寫爲的try/catch塊測試 - 所以我不能寫在try/catch-因爲TDD說「如果燈是紅色的,只能寫代碼」。

這是一個厄運循環...

我希望你有我! 謝謝!

回答

4

充分利用測試本身拋出異常:

public void testShouldReturnReversedStringOfBar() 
    throws Exception 
{ 
    Bar bar = new Bar(); 

    assertEquals("esnesnon", bar.getReversedString()); 
} 

如果有異常拋出,則測試將被標記爲錯誤;這是「一次失敗,但並不像我們所知道的那樣,吉姆」 - 無論如何都失敗了。


而且順便說一句,投擲Exception是不好的做法;當你捕獲Exception時,你也可以捕獲所有的RuntimeException,也就是說,所有未經檢查的異常。不要這樣做。

+0

謝謝!但是對於你的解決方案,我必須爲每個使用getReversedString()方法的方法添加「throws Exception」。由於例外將永遠不會被拋出,我認爲這是不好的做法。我需要一個測試,迫使我在Bar中寫入try/catch-block。 – 2014-12-27 17:49:46

+1

「由於例外永遠不會拋出,我認爲這是不好的做法」 - 不,不是。如果引發異常,則測試失敗,就是這樣。而且,再次,不要拋出異常。拋出一個更具體的類型(最好是不會擴展'RuntimeException'的類型)。 – fge 2014-12-27 17:56:39

+0

我認爲你是對的。也許這是最好的解決方案。順便說一下,在我的程序中它是一個IOException。 – 2014-12-27 17:59:19

0

您可以添加一個throws聲明到fge已經提出的測試方法,或者你可以考慮通過將你的if分成兩個單獨的方法來重新設計你的代碼(一個拋出異常,另一個不拋出)

class Foo { 

    public String getStringWithException() throws Exception { 
     // return data or throw exception if something goes wrong 
    } 

    public String getStringWithoutException() { 
     // return data 
    } 

}

+0

謝謝,但那是不可能的,因爲它是第三方庫。 – 2014-12-27 17:51:05

0

TDD是一種方法,幫助您確認您的程序可以正常工作。儘管Exception不會發生。我認爲你可以在junitthrow Exception測試方法。就像:

public void testShouldReturnReversedStringOfBar() throw Exception{ 
    .... 
}