适当使用断言

能帮助我更好地理解,“断言”与“抛出exception”的适当用法是什么? 每个场景何时适用?

情景1

public Context(Algorythm algo) { if (algo == null) { throw new IllegalArgumentException("Failed to initialize Context"); } this.algo = algo; } 

测试

 public void testContext_null() { try { context = new Context(null); fail(); } catch (IllegalArgumentException e) { assertNotNull(e); } } 

场景2

 public Context(Algorythm algo) { assert (algo != null); this.algo = algo; } 

测试

 public void testContext_null() { try { context = new Context(null); fail(); } catch (AssertionFailedError e) { assertNotNull(e); } } 

断言的主要区别是;

  • 能够按类/包打开/关闭所选测试。
  • 错误抛出。

对于将在生产中关闭的测试,断言更加合适。

如果您希望每次都检查一次测试,例如,如果validation来自输入的数据,则应使用每次运行的检查。

Assert是一个宏(在C / C ++中,或在其他语言中的函数),它将给定表达式validation为true或false,并在false值的情况下抛出exception。

断言是ddebugging应用程序时要使用的东西,比如当你必须检查一个数学表达式是否真的给你一个合适的值,或者一个对象/结构成员是否为null或缺少重要的东西时,以及类似的东西。

抛出exception更像是一种真正的error handling。 例外也是错误并且可以停止您的应用程序,但它们被用作应用程序的(假设)“零售版本”error handling。 这是因为可以使用一些非技术性消息而不是符号和内存地址来捕获exception并以不同方式对用户进行捕获,例如,您可以将其序列化为应用程序日志。

另一方面,断言将停止正在运行的进程并给你一条消息,例如“在source_file.ext,X行上断言失败。该进程将被终止。” 这不是用户友好的:)

当无法满足条件时,应使用assert关键字违反程序的完整性。 这些是不可恢复的错误情况。

另一方面,exception会提醒调用方法以确定错误的存在和位置,但可以由程序员自行决定处理或忽略。

在测试时,如果必须满足条件才能通过测试,则应使用Assert函数。 如果您期望在该特定测试中出现exception,则JUnit 4具有注释以表示测试应该抛出特定的exception:

 @Test(expected=MyException.class) 

在测试代​​码之外,断言通常是个坏主意。 原因是,除非有非常严格的公司准则,否则你总是混合使用,这很糟糕。 断言基本上有两种使用场景:

  1. 额外的,可能是慢速测试,将在生产中关闭
  2. 正常的,快速的代码健全性测试,永远不应该被禁用(比如要求给定的方法参数为非null)

只要你总是遵循其中一个场景,事情就好了。 但是,如果您的代码库最终都是两个场景,那么您就会陷入困境。 你有跟随方案2的断言,你不想禁用它,并且你有断言跟随你要禁用的方案1(并且正在减慢你的生产代码)。 该怎么办?

我使用过的大多数代码库都使用了普通代码中的断言,从来没有因为这个原因而在生产构建中禁用它们。 因此,我的建议总是在测试代码之外避免它们。 使用普通代码的正常exception,并将额外的,可能很慢的代码(带有断言)粘贴在单独的测试代码中。