当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《JUnit测试抛出异常的错误形式?》经验,为你挑选了3个好方法。

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

例如,假设我正在为IPAddress类编写测试.它有一个构造函数IPAddress(String addr),如果addr为null,它将抛出InvalidIPAddressException.据我在google搜索时可以看出,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> Pascal Thive..:

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

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);
}

不错,不是吗?

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


@Test(expected = ...)表单实际上可能比显式try/catch更差,例如,如果测试的"setup"部分可以抛出预期的异常.您将丢失错误本地化,即使执行的方法停止抛出正确的异常,您的测试也可以保持绿色.
try-catch方法允许您测试抛出异常的特征,如果这在上下文中是一件有趣的事情.

2> Brian Agnew..:

对于我不期望例外的测试,我不打算抓住它.我让JUnit捕获异常(它可靠地执行此操作)并且除了声明throws原因(如果需要)之外根本不满足它.

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

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

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

我将此用于我正在测试抛出异常的所有测试.它比我必须与Junit3一起使用的等效捕获/失败模式更简洁.



3> s106mo..:

从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)而是图书馆).虽然我可以理解他的论点,但我认为如果你不想引入另一个第三方库,使用该规则就好了(使用该规则比手动"捕获"异常更好).

推荐阅读
mobiledu2402851203
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有