TDD如何与Exceptions和参数验证一起使用?

Joh*_*ker 1 debugging tdd unit-testing exception

我来到了一个十字路口.我最近写了一个没有TDD的10,000行应用程序(我知道这个错误).我肯定遇到了很多错误,但现在我想改造项目.这是我遇到的问题.让我们举一个分裂功能的例子:

public int divide (int var1, int var2){
if (var1 == 0 || var2 == 0)
   throw new RuntimeException("One of the parameters is zero");
return var1 / var2;
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我抛出一个运行时错误,以便我可以失败,至少发现我的代码在某个地方被破坏了.问题是2倍.首先,我是否在这里正确使用了例外情况?其次,如何编写测试来处理此异常?显然我希望它通过测试,但在这种情况下,它会抛出异常.不太确定如何解决这个问题.是否有一种不同的方式通常用TDD处理?

谢谢

Bil*_*ard 9

首先,你的第一个参数(分子)为零可能不应该引发异常.答案应该是零.仅在用户尝试除以零时抛出异常.

其次,有两种方法(使用JUnit)来测试它们应该抛出的异常.第一个"经典"方法:

@Test
public void testForExpectedExceptionWithTryCatch()
        throws Exception {
    try {
        divide (1, 0);
        fail("division by zero should throw an exception!");
    } catch (RuntimeException expected) {
        // this is exactly what you expect so 
        // just ignore it and let the test pass
    }
}
Run Code Online (Sandbox Code Playgroud)

JUnit 4中较新的方法使用注释来减少需要编写的代码量:

@Test(expected = RuntimeException.class)
public void testForExpectedExceptionWithAnnotation()
        throws Exception {
    divide (1, 0);
}
Run Code Online (Sandbox Code Playgroud)

在这里,因为我们添加(expected = RuntimeException.class)了注释,如果调用divide 抛出,测试将失败RuntimeException.


Chr*_*isF 6

回答你的第一个问题:

如果分母参数很可能divide为0,那么您不应该使用异常处理来捕获错误.例外情况很昂贵,不应用于控制程序流程.因此,您仍应检查,但返回错误代码(或使用可空类型作为返回值),并且您的调用代码应检查此并正确处理它.

public int? divide (int var1, int var2)
{
    if (var2 == 0)
    {
        return null;  // Calling method must check for this
    }
    return var1 / var2;
}
Run Code Online (Sandbox Code Playgroud)

如果零是真正的例外 - 例如,它们不应该被传递 - 那么就像你现在那样做.

回答你的第二个问题:

在检查失败代码的测试方法中,您需要一个异常处理程序:

try
{
    divide (1, 0);
    // If it gets here the test failed
}
catch (RuntimeException ex)
{
    // If it gets here the test passed
}
Run Code Online (Sandbox Code Playgroud)