如果我使用try / catch,为什么我的C#单元测试异常会失败?

时间:2015-07-05 09:15:02

标签: c# unit-testing nunit

我正在使用带有nUnit的C#对我的项目进行单元测试,并且我试图编写一些单元测试来确保调用某个Exception但我的测试仍然失败。在经过大量测试以解决问题之后,我设法确定了它的原因,并创建了一个小代码示例,显示了我的问题。

我的单元测试代码:

    [Test]
    public void TestExceptionIsRaised()
    {
        var ex = Assert.Throws<UnauthorizedAccessException>(() => TestExceptionMethod());
        StringAssert.Contains("Attempted to perform an unauthorized operation", ex.Message);
    }

我的方法没有错误检查:

public void TestExceptionMethod()
{
    throw new UnauthorizedAccessException();
}

现在,如果我使用上述方法运行该单元测试...它会抛出异常,nUnit会检测到它并且测试通过。但是,这段代码是一个问题,因为它没有错误处理,如果我这样发布它会崩溃。

所以为了解决这个问题,我在我的方法中添加了一些错误处理,如下所示:

   public void TestExceptionMethod()
    {
        try
        {
            throw new UnauthorizedAccessException();
        }
        catch (UnauthorizedAccessException ex)
        {
            // Do something about the error
        }
    }

但是现在当我运行单元测试时,它会因此错误而失败:

  

预期:System.UnauthorizedAccessException   但是:null

因此,我不必在单元测试或正确的错误处理之间进行选择,而是试图像这样重新抛出错误:

public void TestExceptionMethod()
        {
            try
            {
                throw new UnauthorizedAccessException();
            }
            catch (UnauthorizedAccessException ex)
            {
                // Do something about the error
                throw;
            }
        }

最后,现在一切正常。单位测试每次都通过。我的方法仍然可以捕获错误并对其做些什么。

但是从我所听到的情况来看,重新抛出这样的错误并不是一种好的做法。所以我只是想知道我的解决方案&#34;正确&#34;?或者是否有更好的单元测试方法,而不必从原始方法中删除try / catch块?

3 个答案:

答案 0 :(得分:2)

  

然而,从我所听到的情况来看,保持这种做法并不是一件好事   重新抛出这样的错误???

重新抛出异常没有错。在应用程序运行一些日志代码而不恢复应用程序状态之后,重新抛出异常实际上是最佳做法。

  

或者没有更好的单元测试方法   必须从原始方法中删除try / catch块?

我不确定我明白你的意思。但是如果你期望从你的方法中抛出异常,那么无论是直接抛出还是重新抛出你的测试都必须有一个例外。如果您try/catch喜欢这样:

public void TestExceptionMethod()
    {
        try
        {
            throw new UnauthorizedAccessException();
        }
        catch (UnauthorizedAccessException ex)
        {
            // Do something about the error
        }
    }

测试将无法确定,因为吞下例外。测试无法检测到方法内部存在异常。

答案 1 :(得分:1)

将您的考试翻译成英语:

  

“我希望方法TestExceptionMethod抛出一个   UnauthorizedAccessException。其中的消息将包含一个   带有更多细节的字符串。“

如果没有抛出异常,这个测试永远不会通过。如果您不想抛出异常,则需要更改测试。如果您确实希望抛出异常,那么您所做的就是正确的。

这是正确的吗?

这取决于。如果您正在做的是一个特殊问题,那么抛出异常。让程序崩溃。修复错误。

另一方面,如果这是预期的事情,例如糟糕的用户输入,边界条件,请尽可能处理。如果您无法从问题中恢复,则抛出异常。

答案 2 :(得分:0)

异常处理效果不佳会使调试变得更加困难,尤其是在吞下异常时,或者创建新的异常实例并抛出丢失原始异常的堆栈跟踪时。当你需要在调用堆栈的更高处需要更抽象的异常时,有时后者是可取的,在这种情况下,你可以将原始异常添加为内部异常以保持对堆栈跟踪的访问。