JUnit 测试的表单不正确,无法引发异常?

2022-08-31 17:14:50

我对 JUnit 很陌生,我真的不知道异常和异常处理的最佳实践是什么。

例如,假设我正在为 IPAddress 类编写测试。它有一个构造函数 IPAddress(String addr),如果 addr 为 null,它将引发 InvalidIPAddressException。据我所知,从谷歌搜索中可以看出,null参数的测试将如下所示。

@Test
public void testNullParameter()
{
    try
    {
        IPAddress addr = new IPAddress(null);
        assertTrue(addr.getOctets() == null);
    }
    catch(InvalidIPAddressException e)
    {
        return;
    }

    fail("InvalidIPAddressException not thrown.");
}

在这种情况下,try/catch是有意义的,因为我知道异常即将到来。

但是现在,如果我想编写 testValidIPAddress(),有几种方法可以做到这一点:

方式#1:

@Test
public void testValidIPAddress() throws InvalidIPAddressException
{
    IPAddress addr = new IPAddress("127.0.0.1");
    byte[] octets = addr.getOctets();

    assertTrue(octets[0] == 127);
    assertTrue(octets[1] == 0);
    assertTrue(octets[2] == 0);
    assertTrue(octets[3] == 1);
}

方式#2:

@Test
public void testValidIPAddress()
{
    try
    {
        IPAddress addr = new IPAddress("127.0.0.1");
        byte[] octets = addr.getOctets();

        assertTrue(octets[0] == 127);
        assertTrue(octets[1] == 0);
        assertTrue(octets[2] == 0);
        assertTrue(octets[3] == 1);
    }
    catch (InvalidIPAddressException e)
    {
        fail("InvalidIPAddressException: " + e.getMessage());
    }
}

标准做法是向 JUnit 抛出意外的异常,还是只是自己处理它们?

感谢您的帮助。


答案 1

实际上,旧的异常测试样式是将 try 块包装在引发异常的代码周围,然后在 try 块的末尾添加一个语句。像这样:fail()

public void testNullParameter() {
    try {
        IPAddress addr = new IPAddress(null);
        fail("InvalidIPAddressException not thrown.");
    } catch(InvalidIPAddressException e) {
        assertNotNull(e.getMessage());
    }
}

这与你写的内容没有太大区别,但是:

  1. 你是没用的。assertTrue(addr.getOctets() == null);
  2. 意图和语法更清晰的IMO,因此更易于阅读。

不过,这有点丑陋。但这正是JUnit 4可以拯救的地方,因为异常测试是JUnit 4中最大的改进之一。使用 JUnit 4,您现在可以像这样编写测试:

@Test (expected=InvalidIPAddressException.class) 
public void testNullParameter() throws InvalidIPAddressException {
    IPAddress addr = new IPAddress(null);
}

很好,不是吗?

现在,关于真正的问题,如果我不希望抛出异常,我肯定会选择#1(因为它不那么冗长),让JUnit处理异常并按预期失败测试。


答案 2

对于我不希望有异常的测试,我懒得抓住它。我让 JUnit 捕获异常(它可靠地做到这一点),除了声明原因(如果需要)之外,根本不满足它。throws

我注意到。您未使用注释可视化的第一个示例。@expected

@Test (expected=IndexOutOfBoundsException.class) public void elementAt() {
    int[] intArray = new int[10];

    int i = intArray[20]; // Should throw IndexOutOfBoundsException
  }

我将其用于我正在测试的所有测试以引发异常。它比我必须与 Junit3 一起使用的等效捕获/失败模式更简短。


推荐