How to use VisibleForTesting for pure JUnit tests

JavaAndroidJunitJunit4Android Testing

Java Problem Overview


I´m running pure JUnit4 java tests over my pure java files on my project but I can't find a way to use @VisibleForTesting clearly without making the thing manually public.

Ex:

@VisibleForTesting
public Address getAddress() {
  return mAddress;
}

The method has to be public to let it be "public" to tests, but in that case the annotation doesn't make sense right? why not just use a comment if the annotation will not do nothing?

Java Solutions


Solution 1 - Java

Make the method package-private and the test will be able to see it, if the test is in the corresponding test package (same package name as the production code).

@VisibleForTesting
Address getAddress() {
  return mAddress;
}

Also consider refactoring your code so you don't need to explicitly test a private method, try testing the behaviour of a public interface. Code that is hard to test can be an indication that improvements can be made to production code.

The point of an annotation is that its convention and could be used in static code analysis, whereas a comment could not.

Solution 2 - Java

According to the Android docs:

> You can optionally specify what the visibility should have been if not for testing; this allows tools to catch unintended access from within production code.

Example:

@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
public Address getAddress()

Solution 3 - Java

The Tag itself helps with the linter to identify unwanted access.

To lower the risk of use it directly, add this methods as internal in Kotlin or protected in Java instead of public and with that only the tests or classes that are in the same package will be able to access that method.

Java:

@VisibleForTesting
protected Address address() {
  return mAddress;
}

Kotlin:

@VisibleForTesting
internal fun address(): Address {
  return address;
}

Solution 4 - Java

@VisibleForTesting annotation is used in package-methods in Guava, and does not part of JUnit API. The annotation is just a tag to indicate the method can be tested. It even doesn't be loaded in JVM.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDaniel Gomez RicoView Question on Stackoverflow
Solution 1 - JavaMikeJView Answer on Stackoverflow
Solution 2 - JavaRodrigo BorbaView Answer on Stackoverflow
Solution 3 - JavaDaniel Gomez RicoView Answer on Stackoverflow
Solution 4 - JavaDanail TsvetanovView Answer on Stackoverflow