簡體   English   中英

如何在junit4 Java中測試多行代碼是否引發異常

[英]How to test if multiple lines of code throw an exception in junit4 Java

我正在為類的方法add(T elem, int index)寫一個否定測試。 如果index < 0 || index > size || elem == null則該方法應引發IllegalArgumentException index < 0 || index > size || elem == null index < 0 || index > size || elem == null 我的測試看起來像這樣:

@Rule
public ExpectedException thrown = ExpectedException.none();

@Test(expected = IllegalArgumentException.class) 
public void addNegTest() {
    l0.add(42, 10);  // index > size 
    l0.add(42, -1);  // index < 0
    l0.add(null, 2); // elem == null
}

該測試變為綠色,但是我發現這三行代碼中只有1個拋出一個異常即可使測試變為綠色。 因此,如果我向這樣的代碼中添加1行,測試仍然會變為綠色。

@Test(expected = IllegalArgumentException.class) 
public void addNegTest() {
    l0.add(42, 10);  // index > size 
    l0.add(42, -1);  // index < 0
    l0.add(null, 2); // elem == null
    l0.add(42, 0);   // this is perfectly fine 
}

那么,如何確保測試測試每一行是否引發一個異常而不僅僅是一個異常?

預期的異常是整個測試方法執行的范圍,無論是否有其他語句不拋出異常。
因此,您應該根據可能的情況創建一種測試方法。

@Test(expected = IllegalArgumentException.class) 
public void add_with_index_greater_than_size() {
    l0.add(42, 10);  // index > size 
}  

@Test(expected = IllegalArgumentException.class) 
public void add_with_index_less_than_zero() {
    l0.add(42, -1);  
}  

@Test(expected = IllegalArgumentException.class) 
public void add_with_null_arg() {
    l0.add(null, 10); 
}  

@Test
public void add() {
    l0.add(42, 10);  
    Assert.assertEquals(42, l0.get(10));
}  

盡管仍然可以使用一個測試方法,但try/catch語句的數量與失敗的場景一樣多,如SilverNak答案所示,但出於可讀性原因,我不建議您使用它。

請注意,除了您的情況外,在自己的方法中指定每個不同的場景是一個好習慣,因為它可以使測試更具可讀性,並且由於其責任更加明確和明確,也使得更容易/更容易糾正失敗的測試。


JUnit 5改進

請注意,使用最新發行的JUnit版本,您可以使用相同的方法收集一些常見情況,而不會降低代碼的可讀性。
您可以收集傳遞給諸如以下錯誤索引的無效案例:

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
...
@Test
public void add_with_index_less_than_zero_or_greater_than_size() {
    Assertions.assertThrows(IllegalArgumentException.class, 
                             () -> l0.add(42, 10));
    Assertions.assertThrows(IllegalArgumentException.class, 
                             () -> l0.add(42, -1));
}  

但我會將其保留在單獨的方法中:

import  org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
...
@Test
public void add_with_null_arg() {
    Assertions.assertThrows(IllegalArgumentException.class, 
                             () -> l0.add(null, 10));
}  

通過編寫四種不同的測試方法:

@Test(expected = IllegalArgumentException.class) 
public void addNegTest_indexTooLarge() {
    l0.add(42, 10);  // index > size 
}

@Test(expected = IllegalArgumentException.class) 
public void addNegTest_negativeIndex() {
    l0.add(42, -1);  // index < 0
}

@Test(expected = IllegalArgumentException.class) 
public void addNegTest_nullElement() {
    l0.add(null, 2); // elem == null
}

@Test
public void addNegTest_ok() {
    l0.add(42, 0);   // this is perfectly fine 
}

如果使用JaCoCo之類的插件,則可以從視覺上確認是否覆蓋了所有可能的路徑。

異常將終止當前執行的方法,直到捕獲到異常為止。 因此,您有兩種可能性:

每種測試一種方法

您可以為每種情況都應拋出異常的情況編寫一種方法:

@Test(expected = IllegalArgumentException.class) 
public void addIndexGreaterThanSize() {
    l0.add(42, 10);  // index > size 
}

@Test(expected = IllegalArgumentException.class) 
public void addIndexNegative() {
    l0.add(42, -1);  // index < 0
}

@Test(expected = IllegalArgumentException.class) 
public void addElementNull() {
    l0.add(null, 2); // elem == null
}

自己捕獲異常

您也可以自己捕獲所有異常,如果未引發異常,則測試失敗。 使用此方法時,可以驗證異常的其他屬性(例如,消息)。

@Test
public void addNegTest() {
    try {
        l0.add(42, 10);  // index > size 
        fail();
    } catch (IllegalArgumentException e) {}
    try {
        l0.add(42, -1);  // index < 0
        fail();
    } catch (IllegalArgumentException e) {}
    try {
        l0.add(null, 2); // elem == null
        fail();
    } catch (IllegalArgumentException e) {}
}

如果確實要測試引發的異常的其他屬性,則可以選擇第二種方法。 否則,我建議第一種選擇,因為它更易於理解,編寫自己的代碼更少。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM