JUnit测试抛出异常的错误形式?

我对JUnit相当陌生,而且我不知道最佳做法是什么对于异常和异常处理。

例如,假设我正在编写IPAddress类的测试。 它有一个构造函数IPAddress(String addr),如果addr为null,将引发InvalidIPAddressException。 据我可以从谷歌搜索来看,空参数的测试看起来像这样。

@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抛出意外的异常还是自己处理它们?

谢谢您的帮助。


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

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

这和你写的没什么不同,但是:

  • 你的assertTrue(addr.getOctets() == null); 没用。
  • 意图和语法更清晰IMO,因此更易于阅读。
  • 尽管如此,这有点难看。 但是这正是JUnit 4开始救援的地方,因为异常测试是JUnit 4中最大的改进之一。使用JUnit 4,您现在可以像这样编写测试:

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

    很好,不是吗?

    现在,关于真正的问题,如果我不期望抛出异常,我肯定会为第一种方式(因为它不那么冗长)让JUnit处理异常并按预期方式通过测试。


    对于那些我不期望有例外的测试,我不打算去捕捉它。 我让JUnit捕捉异常(它可靠地执行此操作),并且除了声明throws原因(如果需要)之外根本不会迎合它。

    我注意到了。 你的第一个例子,你没有使用@expected注释即,

    @Test (expected=IndexOutOfBoundsException.class) public void elementAt() {
        int[] intArray = new int[10];
    
        int i = intArray[20]; // Should throw IndexOutOfBoundsException
      }
    

    我将这个用于所有我正在测试抛出异常的测试。 这比我必须使用Junit3的等效catch / fail模式要简单得多。


    由于JUnit 4.7可以使用ExpectedException规则,因此应该使用它。 该规则使您可以准确定义在测试代码中抛出异常的被调用方法。 而且,您可以轻松地将字符串与异常的错误消息进行匹配。 在你的情况下,代码如下所示:

        @Rule
        public ExpectedException expectedException = ExpectedException.none();
    
        @Test
        public void test() {
            //working code here...
            expectedException.expect(InvalidIPAddressException.class);
            IPAddress addr = new IPAddress(null);
        }
    

    更新:在JUnit实践单元测试和Mockito Tomek Kaczanowski的书中,反对使用ExpectedException,因为规则“打破了单元测试的安排/动作/断言流程”(他建议使用Catch Exception图书馆)。 虽然我可以理解他的论点,但我认为如果不想引入另一个第三方库(使用规则比“手动”捕获异常更好),则使用该规则是很好的。

    链接地址: http://www.djcxy.com/p/64093.html

    上一篇: Bad form for JUnit test to throw exception?

    下一篇: How to instantiate a shared resource in JUnit