如何测试多行代码是否在junit4 Java中抛出异常

Huy*_*ran 1 java junit automated-tests unit-testing exception

我正在add(T elem, int index)为一个类的方法写一个负面测试.该方法预计会抛出IllegalArgumentExceptionif 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
}
Run Code Online (Sandbox Code Playgroud)

测试变为绿色,但我发现这三行代码中只有一行会抛出一个异常,以便测试变为绿色.因此,如果我像这样在代码中添加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 
}
Run Code Online (Sandbox Code Playgroud)

那么我怎样才能确保测试测试每一行是否抛出异常而不只是一个?

dav*_*xxx 6

预期的异常是在整个测试方法执行的范围内,无论其他一些语句是否抛出它.
因此,您应该根据可能的方案创建测试方法.

@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));
}  
Run Code Online (Sandbox Code Playgroud)

虽然你仍然可以使用单个测试方法和尽可能多的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));
}  
Run Code Online (Sandbox Code Playgroud)

但我会用一个单独的方法保留这个:

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));
}  
Run Code Online (Sandbox Code Playgroud)