How to create a TypeMirror instance

I have an AnnotationProcessor that reads spring webmvc annotations and generates code based on what it finds.

The code works fine, but I need to figure out how to unit test a method that takes javax.lang.model.type.TypeMirror

as an argument and returns its representation of a String type, including generics (for example java.util.Map<java.lang.String, java.util.List<java.lang.String>>

- an example of what it would return if I passed TypeMirror

in representing a Map<String, List<String>>

as an argument.

So, to unit test this method (I was basing my code on this answer: Getting the qualified class name of a generic type with a Java 6 annotation handler ) I would like to either mock or create a TypeMirror during unit testing.

In my actual code I get TypeMirror

I need to use VariableElement.asType()

, but running the debugger leads me to conclude that the actual implementation of VariableElement is the main Java class and not part of the api: http://www.docjar.com/docs/api/com/sun/ tools / javac / code / Symbol $ VarSymbol.html

And TypeMirror impl is, similarly buried in the non-public part of the jdk: http://www.docjar.com/docs/api/com/sun/tools/javac/code/Type $ ClassType.html

I would rather not instantiate java's internal types - what's the "correct" way to instantiate TypeMirror

(or VariableElement

)? Has anyone mocked where they could give me an example?

This is the method I want to unit test:

private void typeToString(final TypeMirror type, final StringBuilder result,
                          final char innerClassSeparator) {
    type.accept(new SimpleTypeVisitor7<Void, Void>() {
        @Override
        public Void visitDeclared(DeclaredType declaredType, Void v) {
            TypeElement typeElement = (TypeElement) declaredType.asElement();
            String rawType = rawTypeToString(typeElement, innerClassSeparator);
            result.append(Util.getUnqualifiedClassName(rawType));
            //java.lang.* is auto-included by the compiler for all classes
            if (!rawType.startsWith("java.lang")) {
                importTypes.add(rawType);
            }
            List<? extends TypeMirror> typeArguments = declaredType.getTypeArguments();
            if (!typeArguments.isEmpty()) {
                result.append("<");
                for (int i = 0; i < typeArguments.size(); i++) {
                    if (i != 0) {
                        result.append(", ");
                    }
                    typeToString(typeArguments.get(i), result, innerClassSeparator);
                }
                result.append(">");
            }
            return null;
        }

        @Override
        public Void visitPrimitive(PrimitiveType primitiveType, Void v) {
            result.append(box((PrimitiveType) type).getName());
            return null;
        }

        @Override
        public Void visitArray(ArrayType arrayType, Void v) {
            TypeMirror type = arrayType.getComponentType();
            if (type instanceof PrimitiveType) {
                result.append(type.toString()); // Don't box, since this is an array.
            } else {
                typeToString(arrayType.getComponentType(), result, innerClassSeparator);
            }
            result.append("[]");
            return null;
        }

        @Override
        public Void visitTypeVariable(TypeVariable typeVariable, Void v) {
            result.append(typeVariable.asElement().getSimpleName());
            return null;
        }

        @Override
        public Void visitError(ErrorType errorType, Void v) {
            // Error type found, a type may not yet have been generated, but we need the type
            // so we can generate the correct code in anticipation of the type being available
            // to the compiler.

            // Paramterized types which don't exist are returned as an error type whose name is "<any>"
            if ("<any>".equals(errorType.toString())) {
                throw new CodeGenerationIncompleteException(
                        "Type reported as <any> is likely a not-yet generated parameterized type.");
            }
            result.append(errorType.toString());
            return null;
        }

        @Override
        protected Void defaultAction(TypeMirror typeMirror, Void v) {
            result.append("void");
            return null;
        }
    }, null);
}

      

+3


source to share


1 answer


In general, I would say "this is an interface, so just create a layout." For this case, I think you are testing the wrong seam.



The real unit under test in this case is the anonymously declared implementation SimpleTypeVisitor

. Consider that in order to truly test the entire method, typeToString

you will need to make sure that all six methods that you have implemented match the expected behavior. Therefore, you should push the anonymous implementation into the concrete one and test those methods. Each of them must have at least one test, and in those tests you can mock typeToString

to deal with your recursive calls.

+3


source







All Articles