【问题标题】:JUnit for Functions with Void Return Values用于具有无效返回值的函数的 JUnit
【发布时间】:2010-05-27 14:51:09
【问题描述】:

我一直在开发一个必须使用 JUnit 进行测试的 Java 应用程序。我边走边学。到目前为止,我发现它很有用,尤其是与 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,所以我确信现有的工具可以使这个过程变得更容易。谢谢!

【问题讨论】:

  • void 函数一般都有副作用,你能测试一下吗?

标签: unit-testing junit exception


【解决方案1】:

确实,如果您使用的是 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);
}

【讨论】:

  • 我已经重写了我的测试以使用这种格式。这要容易得多。谢谢!
  • 请注意,如果使用此语法,如果测试中运行的任何代码抛出 IndexOutOfBoundsException,则测试将通过。有时这不是问题,因为您已经拥有涵盖非异常情况的测试用例,但不要在长时间测试中这样做。如果您使用 JUnit 4.7。尝试 ExpectedException 规则:infoq.com/news/2009/07/junit-4.7-rules
【解决方案2】:

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

那么你的第一个例子可以重写为:

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

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

您还应该测试特定异常。

【讨论】:

    【解决方案3】:

    看起来您重新实现了大部分 JUnit :) 通常您不需要这样做。您只需调用要调用的函数并比较结果。如果它抛出异常,JUnit 会为您捕获 if 并导致测试失败。如果您希望出现异常,则可以使用显式注释(如果您使用的是 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 将无法通过测试。

    所以总结一下,恐怕我认为你的方法过于复杂,抱歉。

    【讨论】:

      【解决方案4】:

      如果我错了,请纠正我。正如我从提供的代码中了解到的那样,您只是在执行函数时检查是否可能出现异常。但是您实际上并没有验证被调用的函数是否“正常工作”,除非在发生错误时结束的唯一方法是异常。我建议编写这样的额外测试:

      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.
        . . . . . 
      }
      

      verifyTargetFunction 会检查是否调用 targetFunction 会进行预期的更改 - 假设通过返回 true 或 false 来对数据库表进行判断。

      希望对您有所帮助。

      干杯, 马库斯

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-19
        • 1970-01-01
        相关资源
        最近更新 更多