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

本文关键字:我的 异常 单元测试 失败 为什么 try catch 如果 | 更新日期: 2023-09-27 18:01:01

我正在使用C#和UnUnit对我的项目进行单元测试,我正在尝试编写一些单元测试,以确保调用特定的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但是是:空

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

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

终于,一切都正常了。单元测试每次都通过。我的方法仍然可以捕捉到错误并采取措施

然而,据我所知,不断重复这样的错误并不是一种好的做法???所以我只是想知道我的解决方案是否"正确"?或者,有没有更好的方法可以在不必从原始方法中删除try/catch块的情况下对异常进行单元测试?

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

然而,据我所知,保持你犯了这样的错误???

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

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

我不确定我是否理解你的意思。但是,如果您期望方法抛出异常,那么无论是直接抛出还是重新抛出,测试都必须有一个异常才能通过。如果你像这样try/catch

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

测试肯定会失败,因为吞下了异常。测试无法检测到方法内部存在异常。

将你的测试翻译成英语,你说:

"我希望TestExceptionMethod方法抛出未授权访问异常。其消息将包含包含更多详细信息的字符串。">

如果不抛出异常,此测试将永远不会通过。如果不希望抛出异常,则需要更改测试。如果您确实希望抛出异常,那么您所做的操作是正确的。

这是正确的吗

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

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

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