java单元测试测试异常_Java单元测试中出现意外异常
我真的是JUnit的新手和一般的單元測試,我很難找到合適的方法。處理意外異常的更好方法是什么?為什么?
方法A:
首先捕獲預期的,通過消息測試失敗
在最后一個catch塊中,捕獲一般異常并使測試失敗并顯示一些"意外異常已發生"消息
方法B:
只捕獲預期的,失敗的消息
用throws Exception標記測試方法,讓任何意外的"冒泡"完全脫離測試
并且為了增加混亂,通過說"意外異常",我指的是以下任何一種:
被測試的方法聲稱要拋出的異常,但在這種情況下。例如,我的方法拋出IllegalArgumentException和NullPointerException,但是在這個try塊中,我希望它拋出IllegalArgument; NullPointer被認為是意外的。抓住,失敗或冒泡?
一般的例外我真的無法預料
我知道這個問題有點令人困惑,我自己也迷失了,但希望有人會給我任何暗示。不會因為downvotes而責怪你,它仍然值得冒險:)
拋出@Test注釋不期望的異常的測試將被標記為失敗。 期望拋出多個異常的單元測試不再是單元測試。
使用JUnit的測試方法,基本上,如果方法設法無錯誤地結束,JUnit會認為測試已通過。所以你應該做的是捕獲應該到達的所有異常。在這種情況下,這是你可以做的:
@Test
public myMethodToTest()
{
try {
/* ... */
/* error should trigger before the following statement : */
fail("Reason");
} catch(GoodException e) { }
// no need to do anything since you expected that error
// You can let the test ends without further statement
}
還有另一種寫作方式:
@Test (expected=IndexOutOfBoundsException.class)
public void elementAt()
{
int[] intArray = new int[10];
int i = intArray[20]; // Should throw IndexOutOfBoundsException
}
如果你仍然想要,你仍然可以捕獲不應該觸發的異常,并執行類似的操作:
@Test
public myMethodToTest()
{
try {
/* ... */
} catch(BadException e) {
fail("Reason");
}
}
即使沒有拋出GoodException,第一個測試也會通過。 它在try塊的末尾沒有fail()調用。 第二個測試可以簡單地讓異常傳播,JUnit會標記它失敗(出錯)是拋出異常。
對啊,對不起,讓我糾正第一次測試。
我非常喜歡以前的樣式,在那里你可以準確地捕獲預期的異常。 使用@Test注釋的expected屬性的問題是,如果從代碼中的錯誤位置(例如某些設置代碼中)拋出了正確的異常,那么測試將通過,即使代碼是 做錯了。 我已經在實際的代碼庫中看到過這種情況。
您可以使用此語法查看SO問題(在Java中斷言異常,如何?)
@Test(expected=NumberFormatException.class);
確保可能拋出預期的異常。
某些方法可能合法地拋出多個異常。例如,如果您正在求解二次方程,則可以預期除以零和負平方根。您應該通過編寫兩個單獨的單元測試來測試每個單元測試,每個單元測試都設計為失敗,因此測試拋出異常。
例:
Pair roots = solveQuadratic(double a, double b, double c) {
//...
}
其中Pair是預期的一對解決方案。
這是我們期望通過的測試。
@Test
public void testQuadratic() {
Pair roots = solveQuadratic(1.0, -5.0, 6.0);
Assert.assertEqual(3.0, roots.largest, 0.000001);
Assert.assertEqual(2.0, roots.smallest, 0.000001);
}
這是我們期望失敗的一個:
@Test
public void testQuadraticDivideByZero() {
try {
Pair roots = solveQuadratic(0.0, -5.0, 6.0);
Assert.fail("should have failed with ArithmeticException");
} catch (ArithmeticException e) {
}
}
在這種情況下,您可能希望編寫代碼以便捕獲a=0.0并使用消息拋出IllegalArgumentException。
一般來說,你應該想到所有可能出錯的東西并捕獲它們并測試陷阱。因為某天有人會將a=0.0傳遞給此方法并需要明確的錯誤消息。
我感覺到,到目前為止,沒有一個答案真正達到了問題的目的。 OP明確要求處理意外的異常。我在這個主題上的兩分錢是:
這取決于您想要達到的詳細程度:
通常,您應該努力進行簡短的測試,以確定代碼的一個方面。理想情況下,只需調用少數方法,其中只有一個或兩個可能引發意外異常。在這種情況下,為所有已檢查的異常添加throws子句應足以在測試失敗時分析問題。我更喜歡這種解決方案,因為它更容易編寫,更短,更全面。
例:
@Test
public void testPrivateMethod() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//...
Method method = MyClass.class.getMethod("privateMethod");
method.setAccessible(true);
boolean result = method.invoke(myInstance);
assertTrue(result);
}
如果測試代碼需要更復雜,則多個方法可能會引發異常。可能有些人甚至會拋出同類異常。在這種情況下,try-catch塊可能有助于在測試用例失敗時定位問題。但是,這會產生更多代碼,并可能使測試的可讀性降低。
例:
@Test
public void testPrivateMethod() {
//...
Method method;
try {
Method method = MyClass.class.getMethod("privateMethod");
method.setAccessible(true);
boolean result = method.invoke(myInstance);
assertTrue(result);
} catch (NoSuchMethodException | SecurityException e) {
fail("Could not access method 'privateMethod'.");
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
fail("Call to 'privateMethod' raised an exception.")
}
}
我希望我的意圖是正確的。
擁有測試用例的想法是通過為所有邊界條件提供輸入來避免所有意外的異常。
如果該方法拋出一些Exceptions(該方法具有throws子句并且它嘗試通過一些已檢查的異常通知調用者),則傳遞使您的測試用例拋出該異常的輸入,并在您的測試用例中輸入catch。這使得其中一個測試用例PASS。
如果該方法拋出了意外的異常,請修復該方法。一個方法應該足夠穩定,不要拋出意外的異常,比如NullPointerException,應該修復。
因此,要回答您的問題,處理意外異常的更好方法是通過增強您修復它的測試用例來找到它們。
UNIT測試方法的想法是確保它是一種可靠的方法。可靠性意味著對于給定的輸入,輸出始終是預期的輸出。因此,它取決于方法的預期是否存在異常。如果我們認為發生了意外的異常并且預計方法無法對其進行任何操作,那么您可以將測試用例標記為PASSED。但是,如果期望該方法處理任何異常情況并且如果不能,則將測試用例標記為FAILED。
總結
以上是生活随笔為你收集整理的java单元测试测试异常_Java单元测试中出现意外异常的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 职场任我行——软件测试工程师
- 下一篇: 人工智能自然语言处理NLP入门教程