如果没有c#异常,如何处理和测试流量控制?

时间:2015-09-29 12:42:25

标签: c# unit-testing mstest

如果没有例外情况,对于无效的方法处理和测试流量控制的正确方法是什么?我已经看到微软不推荐这样的做法,那么正确的方法是什么?

这就是我如何处理不应该在我的方法中接受的参数:

    public void RentOutCar(ReservationInfo reservationInfo) 
    {
        try
        {
            if (string.IsNullOrEmpty(reservationInfo.ReservationNumber) || string.IsNullOrWhiteSpace(reservationInfo.ReservationNumber))
            {
                throw new ArgumentException("Reservation Number is null or empty.");
            }
            if (reservationInfo == null)
            {
                throw new ArgumentNullException("Null Reservation info.");
            }
            if (reservationInfo.Car == null)
            {
                throw new ArgumentNullException("No car registered to rent.");
            }
            if (reservationInfo.RentalDatetime == DateTime.MinValue || reservationInfo.RentalDatetime == DateTime.MaxValue)
            {
                throw new ArgumentException("Rental Date has an unreal value.");
            }
            if (reservationInfo.Car.Mileage <0)
            {
                throw new ArgumentOutOfRangeException("Mileage can't be less than 0.");
            }

            reserverationsRegister.ReservationsDone.Add(reservationInfo);
        }
        catch (Exception) 
        {
            throw;
        }

    }

2 个答案:

答案 0 :(得分:4)

这不是微软在说you should not control flow with exceptions时的意思。

  

虽然使用异常处理程序来捕获错误和其他事件   破坏程序执行是一种很好的做法,使用   异常处理程序作为常规程序执行逻辑的一部分可以   价格昂贵,应该避免。

换句话说,在try块中的代码可能抛出并代表合法程序逻辑的情况下,不应抛出(并随后捕获)异常。

用异常控制流程的一个人为设想的例子可能如下:

int x = GetUserInput();
try
{
    MustAcceptPositiveInput(x);
}
catch (InputIsNonPositiveException)
{
    MustAcceptNonPositiveInput(x);
}

等效的“正确”代码可能如下所示:

int x = GetUserInput();
if (x > 0)
{
    MustAcceptPositiveInput(x);
}
else
{
    MustAcceptNonPositiveInput(x);
}

例外情况应保留用于特殊情况,不属于预期程序执行的情况。它会产生更具可读性,更少令人惊讶且性能更高的代码。

您在代码中所做的事情很好(除了@Clay提到的冗余try-catch和错误的测试顺序),您正在验证特殊值的输入,那些代码不适合的值处理

答案 1 :(得分:3)

如果输入无效,则抛出异常是正常的。首先测试reservationInfo为null - 或者你的其他测试会以意想不到的方式中断。另外 - 如果您要做的就是重新抛出它,那么将测试包装在try / catch中是没有意义的。

这不是您在评论中添加的文章中描述的“控制流”问题 - 此处抛出异常是合适的。

您可以考虑在try / catch中仅包装“工作代码”,但前提是您可以从(或可能记录)任何异常中恢复:

try
{
  reserverationsRegister.ReservationsDone.Add(reservationInfo);
}
catch( Exception ex )
{
  LogError( ex );
  throw;
}