I would like to test my utility class ElementUtils but I don't know how to get a class as an Element. In AnnotationProcessors I get my elements by using the following code
Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(annotation);
but since the RoundEnvironment is not available in the tests this is not an option.
Is there any way to get a class as an javax.lang.model.element.Element?
You can use a JUnit @Rule to invoke a compiler run during the test, at which point you may then use Types and Elements utility classes to obtain TypeMirror and Element instances.
Such a rule has been created and is a part of http://github.com/google/compile-testing and can be used thusly:
public @Rule CompilationRule rule = new CompilationRule();
private Elements elements;
private Types types;
@Before
public void setup() {
elements = rule.getElements();
types = rule.getTypes();
}
@Test void testStuff() {
TypeElement typeElement = elements.getTypeElement("some.fully.qualified.ClassName");
// do stuff.
}
Some of what stuff you can do to manipulate (whether in tests or otherwise) TypeMirror and Element instances can be found in the http://github.com/google/auto project in the common sub-module, which contains utilities for managing these java.lang.model classes conveniently.
Element
instances are only valid mid-compile. The docs for equals()
state that "the identity of an element involves implicit state", which in the javac
implementation is actually invalidated once compilation is completed. So, if you're trying to hold references to Element
instances and compare them to other Element
instances in a test, it's not going to work.
That said, you do have some flexibility if you cast a javax.tools.JavaCompiler.CompilationTask
to a com.sun.source.util.JavacTask
. Then, you can manually invoke the parse()
and analyze()
phases and get at Element
instances using the Elements
instance returned from JavacTask.getElements()
.