As per my understanding, these annotations used for methods with an access modifier that allows method invocation from another class for unit testing
#VisibleForTesting - com.google.common.annotations.VisibleForTesting
#TestOnly - org.jetbrains.annotations.TestOnly
The first big difference is obviously that it's provided by different projects.
#VisibleForTesting is part of the Google Guava libraries and #TestOnly is part of JetBrains annotations which are associated with JetBrains, the makers of IntelliJ IDEA, among others.
Comparing the JavaDoc of the two shows that they serve basically identical goals: #TestOnly and #VisibleForTesting.
Note that the documentation of both annotations contain a note effectively warning you that the annotation itself does not prevent production code from calling the annotated method. JetBrains suggests the use of static checking tools that support that annotation (one of which is presumably built into IntelliJ IDEA) and Guava suggests the use of external checker tools with an explicit list of forbidden APIs.
tl;dr They indicate effectively the same thing. The decision which one to use depends mostly on which tools you are using to act on them and which one they support. Already using other annotations or classes from one of those packages is another reason to pick one over the other.
They are not for the same thing.
#VisibleForTesting is used for a methods that could be private/package-visible but has a higher visibility so it can be used by tests. Such a method can still be called in Production.
#TestOnly is used for a method that can only be used by tests, for instance to create a stub or to perform an additional validation only when testing. Such a method should never be called in Production, although the annotation won't prevent that.
By the way, JetBrains provide both annotations, so they can be used in the same project.
Related
Is there a standard way in Java to mark classes, methods etc. that are used by other parts of the program in indirect ways (think: reflection) which are not discoverable by the usual search-functions of IDEs?
In one particular example I have a bunch of classes with a couple of hundred small validation methods. Validation occurs basically by listing all methods of those classes via reflection and executing one by one them on the given object. (It's more complicated than that, but that's the underlying idea)
Now my IDE understandably marks each and everyone of those methods as "unused" because there are never directly called, only via reflection.
A similar problem occurs in another part of the program where several dozen helper classes reside, some of which are almost certainly unused and could be deleted. But: In some rare cases the fields of these classes are accessed via reflection and the usual search functions of the IDE cannot find these usages (again: very understandably so).
I know that it is impossible for the IDE to solve this problem without outside help. Hence my question whether there are already established ways like annotations for example to clearly mark these cases. Of course I could define such an annotation myself, but I'd rather go with an accepted standard if one exists.
Is there even an IDE that can recognise them and warn me automatically if I'm doing stuff like that?
No, there is not a standard way to mark indirect control flow (reflection, Android intents, callbacks, etc.).
There are some tools that provide their own ways to analyze indirect control flow.
For example, the Checker Framework's reflection resolution uses the #MethodVal annotation to indicate the possible targets of a reflective invocation. It also has ways to indicate Android intents.
You typically annotate those classes with #SuppressWarnings("unused") to get rid of IDE warnings
Currently I'm trying to modify method bodies residing in classes already loaded by the JVM. I'm aware of the JVM actually not allowing to change the definition of classes that have already been loaded. But my researches brought me to implementations like JRebel or Java Instrumentation API, both using an agent-based approach. I know how to do it right before a class is loaded o behalf of Javassist. But considering e.g. JRebel in an EJB environment where class definitions are loaded on application startup, shouldn't bytecode modification be possible on JVM-loaded classes?
Well, you learned that the Instrumentation API exists and it offers redefinition of classes as an operation. So then it is time to rethink you initial premise of “the JVM actually not allowing to change the definition of classes that have already been loaded”.
You should note that
as the links show, the Instrumentation API is part of the standard API
the support of redefinition of classes is, however, optional. You may ask whether the current JVM supports this feature
it might be limited to not support every class; you may ask whether it’s possible for a particular class
Even if it is supported, the changes may be limited, to cite the documentation:
The redefinition may change method bodies, the constant pool and attributes. The redefinition must not add, remove or rename fields or methods, change the signatures of methods, or change inheritance. These restrictions maybe be lifted in future versions.
at the time you perform the redefinition, there might be threads executing code of methods of these classes; these executions will complete using the old code then
So the Instrumentation is merely useful for debugging and profiling, etc.
But other frameworks, like EJB containers, offering class reloading in production code, usually resort to creating new ClassLoaders which create different versions of the classes which then are entirely independent to the older versions.
In a Java runtime environment, the identity of a class consists of a pair of <ClassLoader, Qualified Name> rather than just a qualified name…
I wasn't aware that you can use the instrumentation API to redefine classes (see #Holger's answer). However, as he notes, there are some significant limitations on that approach. Furthermore, the javadoc says:
"This method is intended for use in instrumentation, as described in the class specification."
Using it to materially change the semantics of a class is ... all sorts of bad from the perspective of the Java type system.
I'm trying to use PowerMock as a library in another application. Is there a way to use it to mock a static method call without using annotations (I'm in Clojure which doesn't really do annotations)
According to powermock support and this blog, I guess there is no way to avoid annotations in test. I guess we need the #PrepareForTest(StaticClass.class) however. So I believe it is not possible to avoid #PrepareForTest atleast. May be I am wrong, but just thought of sharing what I found.
In fact, it's possible, although the way to final solution is painful.
PowerMock runner just initializes test environment in different classloader, in which the classes specified in PrepareForTest annotation are tweaked by Javassist. So assumed you mimic the work of the classloader and call Javassist by yourself, you can achieve the same effect.
As an example, I utilized PowerMock (internals without annotations) to discover name of method for given method reference. Further info can be found on my blog (in Czech, with working examples). I emphasize such an usage is only experimental and not suitable for production usage.
Are there any Java runtime exploring tools? I mean the tools allowing to invoke concrete objects' methods in the running application (to check the correct behavior). It would be nice if I could substitute the object with another object of this type also, may be instantiated from sketch or deserialized from some source. As I looked, usual debuggers are limited in this possibilities, but I dont pretend to the fact Ive checked all of them.
I would suggest bytecode manipulation frameworks like ASM or BCEL for this purpose.
I would use basic jUnit and EasyMock for creating different input mock objects to check the behavior of your class in different situations. Then in the end you have a nice set of unit tests to maintain your codebase.
You should be able to achieve this at a higher level than direct bytecode manipulation using AOP tools such as AspectJ. Here are a couple of pointers:
http://www.ibm.com/developerworks/java/library/j-aspectj2/
http://danielroop.com/blog/2007/10/04/jmock-and-aspectj/
Why at runtime is anyone interested in knowing that a method is deprecated? Can some provide me with some examples?
There are some frameworks and tools that instantiate objects to work with them.
For example, many JavaBean UI editors create instances of the beans and interact with them as the user manipulates the UI they're designing.
Having the #Deprecated annotation available at runtime allows tools such as this to flag deprecated methods, events, properties for the user.
You're assuming that #deprecated is only of interest in the compile phase (IDE, compiler), but its not a stretch to imaging instrumentation scenarios where you require that information.
For example, an IDE can inform you of the number of call sites for a deprecated method, but how would you go about determining the percentage of time your application spends in deprecated methods?
One's runtime is another one's design time, e.g. when writing code that uses an API.
Good question, and I'm stretching to come up with a convincing scenario. All I've got is that I could imagine a application which used a classloader which didn't allow the use of deprecated code. This would require RetentionPolicy.RUNTIME.
That's all I've got...
Couple practical uses that come to mind:
With Velocity you can have a custom Uberspector which logs the actual calls from Velocity templates to any deprecated method and then just by reading the log you can see where the method is used and you can go and edit it out.
With Wicket you can have a security policy which disallows instantiating any class based on the .class contents so it could be possible to make a system which prevents the instantiation of #Deprecated classes if you're not an admin.
Imagine you compile MyClass.class with deprecated methods. If your #Deprecated annotations got lost, your IDE or compiler couldn't warn you when you call those methods from another class.