具有空值返回值的函数的JUnit

时间:2010-05-27 14:51:09

标签: unit-testing junit exception

我一直在研究Java应用程序,我必须使用JUnit进行测试。我正在学习它。到目前为止,我发现它很有用,特别是与Eclipse JUnit插件结合使用时。

在玩了一下之后,我开发了一种一致的方法来为没有返回值的函数构建单元测试。我想在这里分享并请其他人发表评论。您是否有任何建议的改进或替代方法来实现相同的目标?

常用回报值

首先,有一个枚举用于存储代表测试结果的值。

public enum UnitTestReturnValues
{
    noException,
    unexpectedException
    // etc...
}

广义测试

假设正在编写单元测试:

public class SomeClass
{
    public void targetFunction (int x, int y)
    {
        // ...
    }
}

将创建JUnit测试类:

import junit.framework.TestCase;
public class TestSomeClass extends TestCase
{
    // ...
}

在这个类中,我创建了一个函数,用于每次调用正在测试的目标函数。它捕获所有异常并根据结果返回消息。例如:

public class TestSomeClass extends TestCase
{
    private UnitTestReturnValues callTargetFunction (int x, int y)
    {
        UnitTestReturnValues outcome = UnitTestReturnValues.noException;
        SomeClass testObj = new SomeClass ();
        try
        {
            testObj.targetFunction (x, y);
        }
        catch (Exception e)
        {
            UnitTestReturnValues.unexpectedException;
        }
        return outcome;
    }
}

JUnit测试

JUnit调用的函数在函数名称中以小写“test”开头,并且在第一次失败的断言时失败。要在上面的targetFunction上运行多个测试,它将被写为:

public class TestSomeClass extends TestCase
{
    public void testTargetFunctionNegatives ()
    {
        assertEquals (
            callTargetFunction (-1, -1),
            UnitTestReturnValues.noException);
    }

    public void testTargetFunctionZeros ()
    {
        assertEquals (
            callTargetFunction (0, 0),
            UnitTestReturnValues.noException);
    }

    // and so on...
}

如果您有任何建议或改进,请与我们联系。请记住,我正在学习如何使用JUnit,所以我确信现有的工具可以使这个过程更容易。谢谢!

4 个答案:

答案 0 :(得分:3)

确实,如果您正在使用JUnit 3,并且您正在测试是否在方法中抛出或抛出特定异常,则需要使用类似上面定义的try-catch模式。

然而:

1)我认为测试一个带有void返回值的方法然后检查异常还有很多:你的方法是否正确调用(可能是模拟的)依赖项;当使用不同的上下文或不同的依赖关系集等初始化类时,它的行为会有所不同。通过将所有调用包装到该方法,您很难更改测试的其他方面。

我也普遍反对添加代码并增加复杂性,如果可以避免的话;我不认为在检查异常时必须在给定的测试中放置try / catch是一种负担。

2)切换到JUnit 4!它可以很容易地检查预期的异常:

@Test(expected=IndexOutOfBoundsException.class)
public void testIndexOutOfBoundsException() {
    ArrayList emptyList = new ArrayList();
    Object o = emptyList.get(0);
}

答案 1 :(得分:2)

如果您有可能,则应升级到JUnit 4.x。

然后你的第一个例子可以改写为:

@Test(expected=RuntimeException.class)
public void testTargetFunction() {
   testObj.targetFunction (x, y);
}

这里的优点是您可以删除private UnitTestReturnValues callTargetFunction (int x, int y)方法并使用JUnit内置的支持来预期异常。

您还应该测试特定的例外情况。

答案 2 :(得分:1)

看起来你重新实现了大部分JUnit :)一般来说你不需要这样做。您只需调用要调用的函数并比较结果即可。如果它抛出异常,JUnit将为您捕获并且未通过测试。如果您期望发生异常,则可以使用显式注释(如果使用的是JUnit 4),也可以使用以下模式:

public void testThrows()
{
    try {
        obj.DoSth(); //this should throw MyException
        assertFail("Expected exception");
    } catch (MyException e) {
        //assert the message etc
    }
}

再次,如果obj.DoSth()抛出一个不同的异常,JUnit将无法通过测试。

总而言之,我担心我的方法过于复杂,抱歉。

答案 3 :(得分:0)

如果我错了,请纠正我。正如我从提供的代码中理解的那样,您只是在检查执行函数时是否存在异常。但是你实际上没有验证,如果被调用的函数“正常工作”,除非在出现错误的情况下结束的唯一方法是异常。我建议写这样的附加测试:

public void testTargetFunctionSomeValue()  {
  int someValue = 0;
  callTargetFunction(someValue, someValue);
  assertTrue(verifyTargetFunction(someValue, someValue));
}

public boolean verifyTargetFucntion(int someValue, int someValue) {
 // verify that execution of targetFunction made expected changes.
  . . . . . 
}
如果调用targetFunction进行了预期的更改,那么

和verifyTargetFunction将进行实际检查 - 让我们通过返回true或false来说明数据库表。

希望有所帮助。

干杯, 马库斯