【问题标题】:How to instantiate a TypeMirror如何实例化 TypeMirror
【发布时间】:2014-12-18 19:57:44
【问题描述】:

我有一个 AnnotationProcessor,它读取 spring webmvc 注释并根据它找到的内容生成代码。

代码运行良好,但我需要弄清楚如何对将 javax.lang.model.type.TypeMirror 作为参数的方法进行单元测试并返回它的字符串类型表示,包括泛型(例如,java.util.Map<java.lang.String, java.util.List<java.lang.String>> 是它的一个示例如果我将代表Map<String, List<String>>TypeMirror 作为参数传递,则会返回。

所以为了对这个方法进行单元测试(我的代码基于这个答案: Getting the qualified class name of generic type with Java 6 annotation processor) 我想在单元测试期间模拟或创建一个 TypeMirror。

在我的实际代码中,我使用VariableElement.asType() 获得了我需要的TypeMirror,但运行调试器导致我发现VariableElement 的实际实现是一个核心Java 类,而不是api 的一部分: http://www.docjar.com/docs/api/com/sun/tools/javac/code/Symbol$VarSymbol.html

TypeMirror impl 是这样的,同样隐藏在 jdk 的非面向公众的部分中: http://www.docjar.com/docs/api/com/sun/tools/javac/code/Type$ClassType.html

我宁愿不去实例化内部 java 类型——实例化TypeMirror(或VariableElement)的“正确”方式是什么?有没有人嘲笑过一个他们可以给我举个例子的地方?

这是我要单元测试的方法:

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);
}

【问题讨论】:

    标签: java unit-testing annotation-processing


    【解决方案1】:

    对于一般情况,我会说“它是一个接口,所以只需创建一个模拟。”对于这种情况,我认为您正在测试错误的接缝。

    在这种情况下,真正被测试的单元是您匿名声明的SimpleTypeVisitor 实现。考虑到要真正测试整个typeToString 方法,您必须验证您实现的所有六种方法都与它们的预期行为一致。因此,您应该将匿名实现提升为具体实现并测试这些方法。他们每个人都应该至少有一个测试,在这些测试中你可以模拟出typeToString 来处理你的递归调用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-07
      • 2017-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多