Java 断言,与单元测试和异常相比/对比

标签 java unit-testing exception-handling assert

关闭。这个问题是opinion-based .它目前不接受答案。












想改进这个问题?更新问题,以便 editing this post 可以用事实和引用来回答它.

6年前关闭。




Improve this question




这是我的高级一般问题:

为什么要使用断言而不是单元测试和异常处理?

为了澄清我的困惑并说明我的担忧,我将谈谈我对 Java 断言的了解以及我的背景,只要与这一问题相关。

所以,首先,在本周之前,老实说,我什至不知道 Java 框架的断言,也不知道它们的功能,所以我绝对承认我可能无法了解全部情况。话虽如此,我已经成为 Web 开发、数据和 API 开发方面的专业人士近十年了,所以我并不完全天真。

根据我的阅读和讨论,断言通常在开发过程中使用,(几乎)在生产中总是关闭,并将检查后置条件和类不变值;它们可以并且被用于其他事物,但这两个事物似乎是它们当代的主要用途。它们建立在 Java 异常之上,是 Error 的子类型。 ,并在违反时被抛出。关闭时,它们不会增加运行时开销。

然而,对我来说,它们似乎是多余的,尤其是在考虑良好的异常处理技术和良好的单元测试实践时。我没有看到断言会提醒程序员注意异常处理或单元测试不会的错误或问题的任何情况。

按照这种思路,在我看来,它们似乎会造成代码困惑。如果它们不打算在生产中运行并充当开发辅助工具,那么它们在生产代码中的存在有点反模式:您有单独的源文件夹用于测试和测试资源,并且您编写可测试的代码,而不是而不是严格用于测试的代码。每当我发现自己编写代码只是为了可以测试时,就会提醒我糟糕的设计,我会退后一步重新架构我正在做的事情,以便我的代码是可测试的。在我看来,这是违反该范式的一个例子。无论断言存在于何处,它都可以被 try/catch block 、if/then/else 替换并引发适当的异常,或者由一组单元测试替换——至少在我看来是这样。在生产代码中拥有不会在生产期间运行的断言是令人困惑的。它还分散了代码的目的和代码的作用。我发现评估相同条件的测试断言的可读性会大大提高,因为它包含在可以为该确切场景命名和记录的测试中。

其他人能否为这一思路增添洞察力?也许您同意 - 添加示例或解释我的推理。再说一次,也许你认为我错了——说明原因并提供例子来支持你的推理,或者对我看待事物的方式提供反驳。

谢谢大家!

我咨询过的资源,供您引用:

  • http://c2.com/cgi/wiki?DoNotUseAssertions
  • http://geekexplains.blogspot.com/2008/06/asserions-in-java-assertions-vs.html
  • http://www.javapractices.com/topic/TopicAction.do?Id=102
  • http://docs.oracle.com/javase/7/docs/technotes/guides/language/assert.html
  • 最佳答案

    这个话题是关于观点的,所以我只是添加一些关于这个话题的想法。这些并没有涵盖所有方面,但它可以补充其他人的意见。

    有时我使用断言只是为了表达我在编写代码时做了一些假设。简单的例子:我调用方法来获取一般可以是null的值例如按名称查找用户,但在这种特殊情况下,这不会发生,因为例如我正在他的注册中。因此,我跳过了代码中的“空检查”,但我想明确告诉谁之后会阅读我的代码(也许一个月后我 :))我已经考虑过这个选项

    User user = findUser(userId);
    assert user != null : "we are in the middle of registration"
    user.confirmEmail();
    

    显然,我可以使用简单的注释来做到这一点,但在代码困惑时也不会更糟。

    正如您已经提到的,第二个用例是检查不变量。 “学校示例”将是您正在实现合并排序的情况,并且在合并阶段,算法期望您要合并的两个子数组都已经排序(通过前面的步骤)。

    显然,您将实现单元测试来检查排序是否正常,但这只能验证“端到端”的正确性。在大多数情况下这都很好,但是当您实现它时,您会发现您的一个测试失败了。不幸的是,这个测试使用“大输入”并且您所有的“简单”测试都通过了,因此调试问题是不切实际的。由于合并类没有状态并且仅适用于递归和局部变量,因此您无法从外部单元测试中内省(introspection)状态。这是您可以使用断言检查内部不变量的地方。并且一旦不变量失败,您将获得堆栈跟踪(因此您会发现第 4 级递归存在问题),您可以将重要局部变量的实际状态添加到消息中,以便帮助您识别情况错误。这里的断言很好,因为您不想“重新检查”子数组是否在生产期间进行了排序,因为这样的检查可能非常昂贵。

    修复代码后,您可能会想删除此类代码,但这可能取决于具体情况。为什么我们首先要编写单元测试?因为如果我们进行重构,我们想确定我们是否没有破坏任何东西。如果您希望您可能想要重构代码并且您制作的不变量可以保留,您可能希望保留它们以备将来使用。否则,您可以简单地删除它们或根本不使用断言,而只需使用一些临时代码来查找问题。

    关于Java 断言,与单元测试和异常相比/对比,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30630791/

    相关文章:

    java - 我无法从 Google 应用引擎上部署的后端 servlet 连接到我的 google cloud sql 数据库

    unit-testing - BDD 场景什么时候会变得过于具体?

    java - 捕获错误的异常

    java - @ExceptionHandler(Exception.class) 不处理所有类型的异常

    android - 错误膨胀类android.widget.checkbox

    Java:使用字符串作为源代码的一部分

    java - 如何在Java中将用户输入的字符与字典文件进行比较?

    java - 了解 Java 中的链表

    java - 通过宏录制进行 GUI 单元测试

    python - 单元测试实现集合接口(interface)的类?