Intellij IDEA对单元测试中@Nonnull注解的警告

5
假设我有一个方法,其中一些参数被javax @Nonnull注释标注。
public Something supply(@Nonnull SomeObject someObject) {
    (...)
    if (someObject == null) throw new ValidationException("Required parameter is null");
    (...)
}

当我尝试使用显式 null 参数调用此方法时,IDE 会正确地通知我:

somethingSupplier.supply(null);

现在我想要创建一个单元测试,以检查如果由于某种原因传递给此方法的参数为空(假设它是某种验证异常),则是否会引发适当的异常。

如果我尝试像上面的示例中那样调用此方法,IDE 将警告我关于传递 null 给 @Nonnull... 但这正是我想在这里做的。 我可以注释调用或方法甚至测试类与 @SuppressWarnings("ConstantConditions"),但这会使代码混乱,并且我可能不会被警告其他意外错误我在代码中造成的。

那么问题是,我是否可以在测试类中禁用 @Nonnull 的检查? 或者也许我根本不应该对这些情况进行单元测试?


1
@Nonnull注解并不意味着对于null参数总是会抛出NullPointerException异常。实际上,对于private方法而言,我认为这样的要求是资源浪费,因为验证应该在编译时确保null永远不会传递给该方法。因此,当传递null时,NPE可能会作为操作的副作用发生,但显式测试应该已经过时了。 - Holger
好的,假设这个方法是公共的。此外,在该方法的主体中,某些自定义ValidationException在某些时候被抛出,这可能对我很重要(用于回滚或类似操作)。我已经编辑了问题。 - mareckmareck
我认为这是对 @Nonnull 的误用。一个方法应该允许 @Nullable 并且能够优雅地处理 null 情况,或者不允许 null 并期望调用者确保非空性。这就是这些注释的作用。它们不应该被视为应该遵循的 _提示_,否则可以在文档中简单说明,而不需要注释本身。 - AplusKminus
2个回答

13
如果您想测试代码在出错情况下的行为,那么不可避免地需要创建一些违反被测试代码规则的错误代码。如果这些规则可以被IDE检查,显然,这些检查将会检测到并且无法避免地抑制这些警告。
像抑制其他警告一样,您应该尽可能缩小适用抑制的代码范围。例如,您可以在测试代码中创建一个工厂方法,提供这样一种非法值,它可以在类型系统基于检查的监控之下不被察觉。
class IllegalValue {
    @SuppressWarnings("ConstantConditions")
    static @Nonnull <T> T sneakyNullReference() {
        return null;
    }
}

这样,您已将抑制限制在此小单个方法中。在测试用例中,您可以使用IllegalValue.sneakyNullReference()来测试代码的null行为,而无需进行额外的抑制,并因此在测试代码中使用不适当的位置时正确地获得警告。我强烈建议永远不要将sneakyNullReference()的结果存储到变量中,而是直接引用需要的地方,以便更加清晰明了。

也就是说,在您的问题测试中,代码应该像这样:

somethingSupplier.supply(IllegalValue.sneakyNullReference());

因此,读者立即就可以明白在这里测试了什么...


那看起来是个相当不错的想法,我会试一试,谢谢! - mareckmareck
2
@mareckmareck: 在Java 8下,不需要交换@Nonnull<T>的顺序。我之所以使用这个顺序是因为将其视为类型注解而不是方法注解更有意义。 - Holger
你是对的...出于某种原因,IDEA没有将其识别为适当的结构,尽管代码编译良好... - mareckmareck

0

很遗憾,你没有太多的选择。要么忽略警告,要么添加抑制警告行。Intellij可能有一个设置可以让你禁用警告,或者你可以在一个你不注意的窗口中打印警告,但这两种方法都不是很好的解决方案,因为这些选项将消除其他你可能想看到的相关警告。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接