【问题标题】:Do JUnit Assertions ever get disabled?JUnit 断言会被禁用吗?
【发布时间】:2015-08-08 21:51:01
【问题描述】:

Java 断言语句根据配置标志(例如,-ea)有选择地启用/禁用。我在网上读到,使用 JUnit 断言(例如,Assert.assertTrue),您不必担心自己管理断言配置。这到底是什么意思?要么:

1) JUnit 断言(与 Prod 代码混合在一起)永远不会被禁用。它们的行为就像 Validate 语句,并且总是运行。

2) JUnit 测试框架在运行 JUnit 测试时自动启用所有 JUnit 断言。每当应用程序/代码在 JUnit 之外运行时,JUnit 断言方法什么都不做。

3) 默认情况下,JUnit 断言始终处于启用/禁用状态,但有一个自定义配置/标志可用于禁用/启用它们

以上哪项是正确的?

--

编辑:稍微更改了措辞以消除歧义。

【问题讨论】:

  • JUnit 测试永远不会部署到生产环境中(因为它们不是应用程序的一部分),所以没关系。
  • JUnit 只能用于单元测试,不能用于产品
  • JUnit 断言和 Java 断言是完全不同的东西。 JUnit 断言是来自单元测试内部的简单方法调用。它们不存在于不使用 JUnit 的生产代码中。
  • @RvPr:恕我直言,与上面链接的 SO 答案没有冲突。这只是在不同情况下使用的“断言”一词。 assert 关键字通常用于保护某些功能(根据意外输入值进行输入验证)。而 JUnit 断言用于检查某个功能的结果。
  • @RvPr:我还是不同意。第二个问题明确关注测试,而您询问生产代码。其次,我不建议使用assert - 事实上我尽量避免使用它......

标签: java exception junit assert


【解决方案1】:

这个问题似乎在关于何时使用/不使用断言的编码指南方面打开了一大堆蠕虫。我将在此处发布有关 JUnit Assert 语句是否被禁用的直接问题的答案。再往下,你会发现关于使用断言的哲学方面的讨论。


总结:JUnit 断言语句永远不会被禁用,即使在使用 disable-assertions 标志在生产中运行时也是如此。

实验:创建了一个小的 main 函数,它在第一行抛出一个错误。该错误以各种不同的方式实现。然后我像这样从命令行运行应用程序:mvn clean package; java $JAVA_OPTS -cp ....

  1. 通过引发 IllegalArgument 异常引发错误。应用程序因 IllegalArgument 异常而失败。

  2. 通过添加 assert false 并在启用断言 (-ea) 的情况下运行导致错误。申请失败。

  3. 通过添加 assert false 并在禁用断言 (-da) 的情况下运行时引发错误。申请成功。

  4. 通过添加 Assert.assertTrue(false); 并在启用断言 (-ea) 的情况下运行导致错误。应用程序因 AssertionError 而失败。

  5. 通过添加 Assert.assertTrue(false); 并在禁用断言 (-da) 的情况下运行时引发错误。应用程序因 AssertionError 而失败。

做了一个快速的谷歌搜索,看看是否有任何方法可以禁用 JUnit.Asserts。什么也没找到。如果有人知道这样做的方法,请告诉我,因为我相信这是一个重要的区别。

结论:assert 关键字可以使用 -ea 命令行标志启用/禁用。 JUnit.Asserts 无法启用/禁用。如果您想在生产代码中添加断言,那么这将成为一个非常重要的区别。如果您想禁用它们,请使用 assert 关键字。如果您想要一些您知道将始终启用的东西,那么请考虑 JUnit.Assert 或其他一些引发 AssertionErrors 的类似框架。


关于断言使用背后的哲学:

  1. 最好将某种形式的断言添加到您的生产代码中。见:https://docs.oracle.com/javase/8/docs/technotes/guides/language/assert.html#usage

将断言放入您的代码中。在很多情况下使用断言是好的,包括: 内部不变量 控制流不变量 前置条件、后置条件和类不变量

  1. JUnit 断言不能被视为 java assert 关键字的通用替换。后者使您可以禁用它们,而前者则没有。因此,在选择使用这两者中的哪一个时需要做出设计选择。

  2. 异常和断言的用途非常不同,不应互换使用。以下讨论进一步阐明了这一点:When to use an assertion and when to use an exception


相关 StackOverflow 讨论:

assert vs. JUnit Assertions

【讨论】:

  • IMO,你的结论是错误的。 *.junit.* 包中的类不应在生产代码中使用(JUnit 是一个测试框架)。如果您需要运行时断言,我宁愿使用assert(我不喜欢)或其他框架(例如docs.spring.io/spring/docs/current/javadoc-api/org/…)。当然,从技术上讲,人们可以使用这些类 - 正如您所写,这是代码约定/准则的问题......
  • @home 就像我们在同一页上一样:假设您想要一个永远不会禁用的断言,是否有任何功能性理由不在生产中使用 JUnit.assert?我假设您的反对意见是哲学上的(JUnit 类应该只在测试中使用),而不是功能性的。
  • @home 除了 spring.Assert,还有其他的 assert-framework 和 JUnit 一样好吗?由于与使用 JUnit.Assert 相同的原因,在与 Spring 无关的代码中使用 spring.assert 似乎同样令人讨厌。使用 assert 关键字似乎很痛苦,因为它是非描述性的错误消息并且缺乏 JUnit.Assert 提供的功能。
  • @home 很抱歉这么多回复!进一步阅读 SpringFramework.Assert,它实际上并没有抛出 AssertionErrors,而是抛出异常。这本质上使它类似于 Validate 语句,而不是类似于断言。我认为异常与断言之间有重要的区别,它们不应该互换使用。该讨论进一步阐明了这一点:stackoverflow.com/questions/1957645/…
  • 如果你想在生产环境中创建一个永远无法关闭的断言,只需 throw new AssertionError("message")
【解决方案2】:

我认为您对 JUnit 断言和 Java 的内置断言感到困惑。

  1. JUnit 断言是引发AssertionError 异常的方法,并且只能在您的测试代码中使用。 JUnit 代码不应在生产中使用,仅在构建期间/构建之间运行 JUnit 测试时使用。方法名称命名为assertEquals( expected, actual)assertNull(Object) 等。您不能禁用这些断言,因为它们是方法调用。此外,如果您可以禁用所有 JUnit 断言方法调用,那么您的测试代码将毫无用处。

  2. Java 的内置断言是一个以assert 关键字开头的布尔表达式。如果表达式返回 false,那么它也会抛出 AssertionError。这种断言可以在生产环境中禁用以帮助加速您的代码或打开以帮助跟踪错误。您可以阅读有关内置 Java 断言 in the Java Programming Guide

  3. 的更多信息

【讨论】:

  • 当你说“JUnit 断言只应该在测试代码中使用”时,你是说它们应该只在单元/集成测试中使用吗?如果是这样,这似乎与此处给出的建议严重冲突:stackoverflow.com/questions/1957645/… 即,可以/应该将断言放在您的生产代码中,以断言维护某些代码不变量
  • @RvPr 这个问题是关于 Java 断言,而不是 JUnit 断言。是的,JUnit 通常不用于生产代码。 JUnit 断言用于测试。
  • @MatthewFarwell 您是否建议我们在测试代码中使用 JUnit Asserts,在生产代码中使用断言关键字?
  • 是的。在测试中使用 JUnit 断言。我个人不会在任何地方使用 Java 断言,但有些人会这样做。
猜你喜欢
  • 2010-12-20
  • 1970-01-01
  • 2012-12-23
  • 1970-01-01
  • 1970-01-01
  • 2011-02-18
  • 2018-12-23
  • 2011-11-12
  • 1970-01-01
相关资源
最近更新 更多