5

Let's say I have a method with some of the parameters annotated with javax @Nonnull annotation.

public Something supply(@Nonnull SomeObject someObject) {
    (...)
    if (someObject == null) throw new ValidationException("Required parameter is null");
    (...)
}

IDE correctly notifies me, when I try to call this method with explicit null argument, like this:

somethingSupplier.supply(null);

Now what I want to do is create unit test, that checks if proper exception will be thrown, if for some reason the argument passed to this method happens to be null (let's say it's some kind of validation exception).

If I try to call this method like in above example, IDE will warn me about passing null to @Nonnull... but this is exactly what I want to do here. I can annotate the call or the method or even the test class with @SuppressWarnings("ConstantConditions"), but it clutters the code and I might not get warned about other unintentional errors I make in code.

So the question is if I can somehow disable the inspection for @Nonnull in test classes? Or perhaps I shouldn't unit test those cases at all?

mareckmareck
  • 1,560
  • 13
  • 18
  • 1
    The `@Nonnull` annotation does not imply that a `NullPointerException` is always thrown for a `null` argument. In fact, for `private` methods I would consider such a requirement as a waste of resources as the validation is supposed to ensure at compile-time that `null` is never passed to the method. So NPEs *might* occur as a side effect of an operation when passing `null` but explicit tests should be obsolete. – Holger Jul 09 '15 at 10:51
  • Okay, let's say this method is public then. Also, in the body of this method at some point some custom ValidationException is thrown which might be important for me (for rollback or sth like that). I've edited the question. – mareckmareck Jul 09 '15 at 10:58
  • I consider this a misuse of `@Nonnull`. A method should either allow `@Nullable` and properly handle the `null` case gracefully or it should not allow it and then *expect* the non-nullity to be ensured by the caller. That is what these annotations are for. They are not supposed to be _hints_ that _should_ be followed, otherwise that could be simply stated in the documentation and there would be no need for the annotation itself. – AplusKminus Mar 16 '22 at 16:26

2 Answers2

13

If you want to test code behavior for erroneous cases, is it unavoidable to create code which is erroneous regarding the rules of the code under test. If these rules can be checked by an IDE, obviously, these checks will detect that and suppressing these warnings is unavoidable.

As always with suppressing warnings, you should try to narrow the code for which the suppressing applies as much as possible. E.g., you can create a factory method within the testing code providing such an illegal value which flies under the radar of the type system based check:

class IllegalValue {
    @SuppressWarnings("ConstantConditions")
    static @Nonnull <T> T sneakyNullReference() {
        return null;
    }
}

That way you have limited the suppressing to this small single method. Within your test cases you may use IllegalValue.sneakyNullReference() for testing code for its null behavior without additional suppression and hence rightly getting warnings when using null at inappropriate places within the test code. I strongly recommend to never store the result of sneakyNullReference() into a variable but always reference directly where needed, for clarity.

I.e. within the test of your question the code should look like

somethingSupplier.supply(IllegalValue.sneakyNullReference());

so a reader immediately understands what is tested here…

mareckmareck
  • 1,560
  • 13
  • 18
Holger
  • 285,553
  • 42
  • 434
  • 765
  • That looks like a pretty decent idea, I'll try it out, thanks! – mareckmareck Jul 09 '15 at 11:36
  • 2
    @mareckmareck: Swapping the order of `@Nonnull` and `` should not be necessary under Java 8. I used the order because it makes more sense to view it as a type annotation rather than a method annotation. – Holger Jul 09 '15 at 11:51
  • You're right... for some reason IDEA doesn't recognize it as a proper construct, even though the code compiles fine... – mareckmareck Jul 09 '15 at 12:08
0

Unfortunately there isnt much you can do. Either ignore the warnings or add the suppress warnings line. Its possible that intellij has a setting that will let you disable warnings, or you could have warnings printed in a window that you dont pay attention to, but neither is a great solution, as those options will eliminate other relevant warnings that you may want to see.

kingfrito_5005
  • 611
  • 5
  • 15