如果我使用 try/catch,为什么我的异常 C# 单元测试会失败?
Why do my C# unit tests for exceptions fail if I use try/catch?
我正在使用 C# 和 nUnit 对我的项目进行单元测试,我正在尝试编写一些单元测试以确保调用某个异常,但我的测试一直失败。经过大量测试解决问题后,我设法找出了问题的原因并创建了一个小代码示例,在下面显示了我的问题。
我的单元测试代码:
[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
}
}
但是现在当我 运行 单元测试失败并出现此错误时:
Expected: System.UnauthorizedAccessException
But was: null
因此,我不必在单元测试或正确的错误处理之间做出选择,而是尝试像这样重新抛出错误:
public void TestExceptionMethod()
{
try
{
throw new UnauthorizedAccessException();
}
catch (UnauthorizedAccessException ex)
{
// Do something about the error
throw;
}
}
终于,现在一切正常了。单元测试每次都通过。而且我的方法仍然可以捕获错误并对其进行处理。
然而,据我所知,不断重复抛出这样的错误并不是一个好习惯???所以我只是想知道我的解决方案是 "correct" 吗?或者是否有更好的异常单元测试方法,而无需从原始方法中删除 try/catch 块?
However from what I've heard it isn't good practice to keep
re-throwing errors like this???
重新抛出异常没有错。实际上,在您的应用程序运行一些日志代码 而不恢复您的应用程序状态 后重新抛出异常是最佳实践。
Or is there a better way of unit testing for an exception without
having to remove the try/catch blocks from the original method?
我不确定我明白你的意思。但是如果你希望你的方法抛出异常,那么无论是直接抛出还是重新抛出,你的测试都必须有一个异常才能通过。如果你try/catch
喜欢这样:
public void TestExceptionMethod()
{
try
{
throw new UnauthorizedAccessException();
}
catch (UnauthorizedAccessException ex)
{
// Do something about the error
}
}
测试肯定会失败,因为异常被吞噬了。测试无法检测到方法内部有异常。
将你的测试翻译成你说的英语:
"I expect the method TestExceptionMethod to throw a
UnauthorizedAccessException. The message of which will contain a
string with more details."
如果不抛出异常,此测试将永远不会通过。如果您不想抛出异常,则需要更改测试。如果您确实希望抛出异常,那么您所做的是正确的。
这是正确的吗?
视情况而定。如果你正在做的是一个异常问题,那么抛出一个异常。让程序崩溃。修复错误。
另一方面,如果这是意料之中的事情,例如错误的用户输入、边界条件,请尽可能处理它。如果您无法从问题中恢复,则抛出异常。
异常处理做得不好会使调试变得更加困难,尤其是当异常被吞噬时,或者当创建并抛出新的异常实例时丢失了原始异常的堆栈跟踪。有时,当您需要调用堆栈更高层的更抽象的异常时,后者是可取的,在这种情况下,您可以将原始异常添加为内部异常以保持对堆栈跟踪的访问。
我正在使用 C# 和 nUnit 对我的项目进行单元测试,我正在尝试编写一些单元测试以确保调用某个异常,但我的测试一直失败。经过大量测试解决问题后,我设法找出了问题的原因并创建了一个小代码示例,在下面显示了我的问题。
我的单元测试代码:
[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
}
}
但是现在当我 运行 单元测试失败并出现此错误时:
Expected: System.UnauthorizedAccessException But was: null
因此,我不必在单元测试或正确的错误处理之间做出选择,而是尝试像这样重新抛出错误:
public void TestExceptionMethod()
{
try
{
throw new UnauthorizedAccessException();
}
catch (UnauthorizedAccessException ex)
{
// Do something about the error
throw;
}
}
终于,现在一切正常了。单元测试每次都通过。而且我的方法仍然可以捕获错误并对其进行处理。
然而,据我所知,不断重复抛出这样的错误并不是一个好习惯???所以我只是想知道我的解决方案是 "correct" 吗?或者是否有更好的异常单元测试方法,而无需从原始方法中删除 try/catch 块?
However from what I've heard it isn't good practice to keep re-throwing errors like this???
重新抛出异常没有错。实际上,在您的应用程序运行一些日志代码 而不恢复您的应用程序状态 后重新抛出异常是最佳实践。
Or is there a better way of unit testing for an exception without having to remove the try/catch blocks from the original method?
我不确定我明白你的意思。但是如果你希望你的方法抛出异常,那么无论是直接抛出还是重新抛出,你的测试都必须有一个异常才能通过。如果你try/catch
喜欢这样:
public void TestExceptionMethod()
{
try
{
throw new UnauthorizedAccessException();
}
catch (UnauthorizedAccessException ex)
{
// Do something about the error
}
}
测试肯定会失败,因为异常被吞噬了。测试无法检测到方法内部有异常。
将你的测试翻译成你说的英语:
"I expect the method TestExceptionMethod to throw a UnauthorizedAccessException. The message of which will contain a string with more details."
如果不抛出异常,此测试将永远不会通过。如果您不想抛出异常,则需要更改测试。如果您确实希望抛出异常,那么您所做的是正确的。
这是正确的吗?
视情况而定。如果你正在做的是一个异常问题,那么抛出一个异常。让程序崩溃。修复错误。
另一方面,如果这是意料之中的事情,例如错误的用户输入、边界条件,请尽可能处理它。如果您无法从问题中恢复,则抛出异常。
异常处理做得不好会使调试变得更加困难,尤其是当异常被吞噬时,或者当创建并抛出新的异常实例时丢失了原始异常的堆栈跟踪。有时,当您需要调用堆栈更高层的更抽象的异常时,后者是可取的,在这种情况下,您可以将原始异常添加为内部异常以保持对堆栈跟踪的访问。